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)  

TextLabel.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  File : TextLabel.cpp
3  Project : LabPlot
4  Description : Text label supporting reach text and latex formatting
5  --------------------------------------------------------------------
6  Copyright : (C) 2009 Tilman Benkert (thzs@gmx.net)
7  Copyright : (C) 2012-2018 Alexander Semke (alexander.semke@web.de)
8  Copyright : (C) 2019 by Stefan Gerlach (stefan.gerlach@uni.kn)
9  ***************************************************************************/
10 
11 /***************************************************************************
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * *
18  * This program is distributed in the hope that it will be useful, *
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
21  * GNU General Public License for more details. *
22  * *
23  * You should have received a copy of the GNU General Public License *
24  * along with this program; if not, write to the Free Software *
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
26  * Boston, MA 02110-1301 USA *
27  * *
28  ***************************************************************************/
29 
30 #include "TextLabel.h"
31 #include "Worksheet.h"
32 #include "TextLabelPrivate.h"
35 
36 #include <QApplication>
37 #include <QBuffer>
38 #include <QDesktopWidget>
39 #include <QGraphicsScene>
40 #include <QGraphicsSceneMouseEvent>
41 #include <QKeyEvent>
42 #include <QMenu>
43 #include <QPainter>
44 #include <QTextCharFormat>
45 #include <QTextDocument>
46 #include <QTextCursor>
47 #include <QtConcurrent/QtConcurrentRun>
48 
49 #include <QIcon>
50 #include <KConfig>
51 #include <KConfigGroup>
52 #include <KLocalizedString>
53 
54 /**
55  * \class TextLabel
56  * \brief A label supporting rendering of html- and tex-formatted texts.
57  *
58  * The label is aligned relative to the specified position.
59  * The position can be either specified by providing the x- and y- coordinates
60  * in parent's coordinate system, or by specifying one of the predefined position
61  * flags (\c HorizontalPosition, \c VerticalPosition).
62  */
63 
64 TextLabel::TextLabel(const QString& name, Type type)
65  : WorksheetElement(name, AspectType::TextLabel), d_ptr(new TextLabelPrivate(this)), m_type(type) {
66 
67  init();
68 }
69 
70 TextLabel::TextLabel(const QString &name, TextLabelPrivate *dd, Type type)
71  : WorksheetElement(name, AspectType::TextLabel), d_ptr(dd), m_type(type) {
72 
73  init();
74 }
75 
77  return m_type;
78 }
79 
81  Q_D(TextLabel);
82 
83  QString groupName;
84  switch (m_type) {
85  case Type::General:
86  groupName = "TextLabel";
87  break;
88  case Type::PlotTitle:
89  groupName = "PlotTitle";
90  break;
91  case Type::AxisTitle:
92  groupName = "AxisTitle";
93  break;
95  groupName = "PlotLegendTitle";
96  break;
97  }
98 
99  const KConfig config;
100  DEBUG(" config has group \"" << STDSTRING(groupName) << "\": " << config.hasGroup(groupName));
101  // group is always valid if you call config.group(..;
102  KConfigGroup group;
103  if (config.hasGroup(groupName))
104  group = config.group(groupName);
105 
106  // non-default settings
107  d->staticText.setTextFormat(Qt::RichText);
108  // explicitly set no wrap mode for text label to avoid unnecessary line breaks
109  QTextOption textOption;
110  textOption.setWrapMode(QTextOption::NoWrap);
111  d->staticText.setTextOption(textOption);
112 
114  d->position.verticalPosition = WorksheetElement::VerticalPosition::Top;
115  d->verticalAlignment = WorksheetElement::VerticalAlignment::Bottom;
116  } else if (m_type == Type::AxisTitle) {
117  d->position.horizontalPosition = WorksheetElement::HorizontalPosition::Custom;
118  d->position.verticalPosition = WorksheetElement::VerticalPosition::Custom;
119  }
120 
121  // read settings from config if group exists
122  if (group.isValid()) {
123  //properties common to all types
124  d->textWrapper.teXUsed = group.readEntry("TeXUsed", d->textWrapper.teXUsed);
125  d->teXFont.setFamily(group.readEntry("TeXFontFamily", d->teXFont.family()));
126  d->teXFont.setPointSize(group.readEntry("TeXFontSize", d->teXFont.pointSize()));
127  d->fontColor = group.readEntry("TeXFontColor", d->fontColor);
128  d->backgroundColor = group.readEntry("TeXBackgroundColor", d->backgroundColor);
129  d->rotationAngle = group.readEntry("Rotation", d->rotationAngle);
130 
131  //border
132  d->borderShape = (TextLabel::BorderShape)group.readEntry("BorderShape", (int)d->borderShape);
133  d->borderPen = QPen(group.readEntry("BorderColor", d->borderPen.color()),
134  group.readEntry("BorderWidth", d->borderPen.width()),
135  (Qt::PenStyle) group.readEntry("BorderStyle", (int)(d->borderPen.style())));
136  d->borderOpacity = group.readEntry("BorderOpacity", d->borderOpacity);
137 
138  //position and alignment relevant properties
139  d->position.point.setX( group.readEntry("PositionXValue", d->position.point.x()) );
140  d->position.point.setY( group.readEntry("PositionYValue", d->position.point.y()) );
141  d->position.horizontalPosition = (HorizontalPosition) group.readEntry("PositionX", (int)d->position.horizontalPosition);
142  d->position.verticalPosition = (VerticalPosition) group.readEntry("PositionY", (int)d->position.verticalPosition);
143  d->horizontalAlignment = (WorksheetElement::HorizontalAlignment) group.readEntry("HorizontalAlignment", static_cast<int>(d->horizontalAlignment));
144  d->verticalAlignment = (WorksheetElement::VerticalAlignment) group.readEntry("VerticalAlignment", static_cast<int>(d->verticalAlignment));
145  }
146 
147  DEBUG("CHECK: default/run time image resolution: " << d->teXImageResolution << '/' << QApplication::desktop()->physicalDpiX());
148 
149  connect(&d->teXImageFutureWatcher, &QFutureWatcher<QImage>::finished, this, &TextLabel::updateTeXImage);
150 }
151 
152 //no need to delete the d-pointer here - it inherits from QGraphicsItem
153 //and is deleted during the cleanup in QGraphicsScene
154 TextLabel::~TextLabel() = default;
155 
156 QGraphicsItem* TextLabel::graphicsItem() const {
157  return d_ptr;
158 }
159 
160 void TextLabel::setParentGraphicsItem(QGraphicsItem* item) {
161  Q_D(TextLabel);
162  d->setParentItem(item);
163  d->updatePosition();
164 }
165 
167  Q_D(TextLabel);
168  d->retransform();
169 }
170 
171 void TextLabel::handleResize(double horizontalRatio, double verticalRatio, bool pageResize) {
172  DEBUG("TextLabel::handleResize()");
173  Q_UNUSED(pageResize);
174  Q_D(TextLabel);
175 
176  double ratio = 0;
177  if (horizontalRatio > 1.0 || verticalRatio > 1.0)
178  ratio = qMax(horizontalRatio, verticalRatio);
179  else
180  ratio = qMin(horizontalRatio, verticalRatio);
181 
182  d->teXFont.setPointSizeF(d->teXFont.pointSizeF() * ratio);
183  d->updateText();
184 
185  //TODO: doesn't seem to work
186  QTextDocument doc;
187  doc.setHtml(d->textWrapper.text);
188  QTextCursor cursor(&doc);
189  cursor.select(QTextCursor::Document);
190  QTextCharFormat fmt = cursor.charFormat();
191  QFont font = fmt.font();
192  font.setPointSizeF(font.pointSizeF() * ratio);
193  fmt.setFont(font);
194  cursor.setCharFormat(fmt);
195 }
196 
197 /*!
198  Returns an icon to be used in the project explorer.
199 */
200 QIcon TextLabel::icon() const{
201  return QIcon::fromTheme("draw-text");
202 }
203 
205  QMenu* menu = WorksheetElement::createContextMenu();
206  QAction* firstAction = menu->actions().at(1); //skip the first action because of the "title-action"
207 
208  if (!visibilityAction) {
209  visibilityAction = new QAction(i18n("Visible"), this);
210  visibilityAction->setCheckable(true);
211  connect(visibilityAction, &QAction::triggered, this, &TextLabel::visibilityChanged);
212  }
213 
214  visibilityAction->setChecked(isVisible());
215  menu->insertAction(firstAction, visibilityAction);
216  menu->insertSeparator(firstAction);
217 
218  return menu;
219 }
220 
221 /* ============================ getter methods ================= */
223 CLASS_SHARED_D_READER_IMPL(TextLabel, QColor, fontColor, fontColor);
224 CLASS_SHARED_D_READER_IMPL(TextLabel, QColor, backgroundColor, backgroundColor);
225 CLASS_SHARED_D_READER_IMPL(TextLabel, QFont, teXFont, teXFont);
226 CLASS_SHARED_D_READER_IMPL(TextLabel, TextLabel::PositionWrapper, position, position);
227 BASIC_SHARED_D_READER_IMPL(TextLabel, WorksheetElement::HorizontalAlignment, horizontalAlignment, horizontalAlignment);
228 BASIC_SHARED_D_READER_IMPL(TextLabel, WorksheetElement::VerticalAlignment, verticalAlignment, verticalAlignment);
229 BASIC_SHARED_D_READER_IMPL(TextLabel, qreal, rotationAngle, rotationAngle);
230 
231 BASIC_SHARED_D_READER_IMPL(TextLabel, TextLabel::BorderShape, borderShape, borderShape)
232 CLASS_SHARED_D_READER_IMPL(TextLabel, QPen, borderPen, borderPen)
233 BASIC_SHARED_D_READER_IMPL(TextLabel, qreal, borderOpacity, borderOpacity)
234 
235 /* ============================ setter methods and undo commands ================= */
236 STD_SETTER_CMD_IMPL_F_S(TextLabel, SetText, TextLabel::TextWrapper, textWrapper, updateText);
237 void TextLabel::setText(const TextWrapper &textWrapper) {
238  Q_D(TextLabel);
239  if ( (textWrapper.text != d->textWrapper.text) || (textWrapper.teXUsed != d->textWrapper.teXUsed) )
240  exec(new TextLabelSetTextCmd(d, textWrapper, ki18n("%1: set label text")));
241 }
242 
243 STD_SETTER_CMD_IMPL_F_S(TextLabel, SetTeXFont, QFont, teXFont, updateText);
244 void TextLabel::setTeXFont(const QFont& font) {
245  Q_D(TextLabel);
246  if (font != d->teXFont)
247  exec(new TextLabelSetTeXFontCmd(d, font, ki18n("%1: set TeX main font")));
248 }
249 
250 STD_SETTER_CMD_IMPL_F_S(TextLabel, SetTeXFontColor, QColor, fontColor, updateText);
251 void TextLabel::setFontColor(const QColor color) {
252  Q_D(TextLabel);
253  if (color != d->fontColor)
254  exec(new TextLabelSetTeXFontColorCmd(d, color, ki18n("%1: set font color")));
255 }
256 
257 STD_SETTER_CMD_IMPL_F_S(TextLabel, SetTeXBackgroundColor, QColor, backgroundColor, updateText);
258 void TextLabel::setBackgroundColor(const QColor color) {
259  Q_D(TextLabel);
260  if (color != d->backgroundColor)
261  exec(new TextLabelSetTeXBackgroundColorCmd(d, color, ki18n("%1: set background color")));
262 }
263 
264 STD_SETTER_CMD_IMPL_F_S(TextLabel, SetPosition, TextLabel::PositionWrapper, position, retransform);
266  Q_D(TextLabel);
267  if (pos.point != d->position.point || pos.horizontalPosition != d->position.horizontalPosition || pos.verticalPosition != d->position.verticalPosition)
268  exec(new TextLabelSetPositionCmd(d, pos, ki18n("%1: set position")));
269 
270 }
271 
272 /*!
273  sets the position without undo/redo-stuff
274 */
275 void TextLabel::setPosition(QPointF point) {
276  Q_D(TextLabel);
277  if (point != d->position.point) {
278  d->position.point = point;
279  retransform();
280  }
281 }
282 
283 /*!
284  * position is set to invalid if the parent item is not drawn on the scene
285  * (e.g. axis is not drawn because it's outside plot ranges -> don't draw axis' title label)
286  */
287 void TextLabel::setPositionInvalid(bool invalid) {
288  Q_D(TextLabel);
289  if (invalid != d->positionInvalid)
290  d->positionInvalid = invalid;
291 }
292 
293 STD_SETTER_CMD_IMPL_F_S(TextLabel, SetRotationAngle, qreal, rotationAngle, recalcShapeAndBoundingRect);
294 void TextLabel::setRotationAngle(qreal angle) {
295  Q_D(TextLabel);
296  if (angle != d->rotationAngle)
297  exec(new TextLabelSetRotationAngleCmd(d, angle, ki18n("%1: set rotation angle")));
298 }
299 
300 STD_SETTER_CMD_IMPL_F_S(TextLabel, SetHorizontalAlignment, TextLabel::HorizontalAlignment, horizontalAlignment, retransform);
301 void TextLabel::setHorizontalAlignment(const WorksheetElement::HorizontalAlignment hAlign) {
302  Q_D(TextLabel);
303  if (hAlign != d->horizontalAlignment)
304  exec(new TextLabelSetHorizontalAlignmentCmd(d, hAlign, ki18n("%1: set horizontal alignment")));
305 }
306 
307 STD_SETTER_CMD_IMPL_F_S(TextLabel, SetVerticalAlignment, WorksheetElement::VerticalAlignment, verticalAlignment, retransform);
308 void TextLabel::setVerticalAlignment(const TextLabel::VerticalAlignment vAlign) {
309  Q_D(TextLabel);
310  if (vAlign != d->verticalAlignment)
311  exec(new TextLabelSetVerticalAlignmentCmd(d, vAlign, ki18n("%1: set vertical alignment")));
312 }
313 
314 //Border
315 STD_SETTER_CMD_IMPL_F_S(TextLabel, SetBorderShape, TextLabel::BorderShape, borderShape, updateBorder)
316 void TextLabel::setBorderShape(TextLabel::BorderShape shape) {
317  Q_D(TextLabel);
318  if (shape != d->borderShape)
319  exec(new TextLabelSetBorderShapeCmd(d, shape, ki18n("%1: set border shape")));
320 }
321 
322 STD_SETTER_CMD_IMPL_F_S(TextLabel, SetBorderPen, QPen, borderPen, update)
323 void TextLabel::setBorderPen(const QPen &pen) {
324  Q_D(TextLabel);
325  if (pen != d->borderPen)
326  exec(new TextLabelSetBorderPenCmd(d, pen, ki18n("%1: set border")));
327 }
328 
329 STD_SETTER_CMD_IMPL_F_S(TextLabel, SetBorderOpacity, qreal, borderOpacity, update)
330 void TextLabel::setBorderOpacity(qreal opacity) {
331  Q_D(TextLabel);
332  if (opacity != d->borderOpacity)
333  exec(new TextLabelSetBorderOpacityCmd(d, opacity, ki18n("%1: set border opacity")));
334 }
335 
336 //misc
337 STD_SWAP_METHOD_SETTER_CMD_IMPL_F(TextLabel, SetVisible, bool, swapVisible, retransform);
338 void TextLabel::setVisible(bool on) {
339  Q_D(TextLabel);
340  exec(new TextLabelSetVisibleCmd(d, on, on ? ki18n("%1: set visible") : ki18n("%1: set invisible")));
341 }
342 
343 bool TextLabel::isVisible() const {
344  Q_D(const TextLabel);
345  return d->isVisible();
346 }
347 
348 void TextLabel::setPrinting(bool on) {
349  Q_D(TextLabel);
350  d->m_printing = on;
351 }
352 
354  Q_D(TextLabel);
355  d->updateTeXImage();
356 }
357 
358 //##############################################################################
359 //###### SLOTs for changes triggered via QActions in the context menu ########
360 //##############################################################################
362  Q_D(const TextLabel);
363  this->setVisible(!d->isVisible());
364 }
365 
366 //##############################################################################
367 //####################### Private implementation ###############################
368 //##############################################################################
370  setFlag(QGraphicsItem::ItemIsSelectable);
371  setFlag(QGraphicsItem::ItemIsMovable);
372  setFlag(QGraphicsItem::ItemSendsGeometryChanges);
373  setFlag(QGraphicsItem::ItemIsFocusable);
374  setAcceptHoverEvents(true);
375 }
376 
377 QString TextLabelPrivate::name() const {
378  return q->name();
379 }
380 
381 /*!
382  calculates the position and the bounding box of the label. Called on geometry or text changes.
383  */
386  return;
387 
390  updatePosition();
391 
392  double x = position.point.x();
393  double y = position.point.y();
394 
395  //determine the size of the label in scene units.
396  double w, h;
397  if (textWrapper.teXUsed) {
398  //image size is in pixel, convert to scene units
399  w = teXImage.width()*teXImageScaleFactor;
400  h = teXImage.height()*teXImageScaleFactor;
401  }
402  else {
403  //size is in points, convert to scene units
404  w = staticText.size().width()*scaleFactor;
405  h = staticText.size().height()*scaleFactor;
406  }
407 
408  //depending on the alignment, calculate the new GraphicsItem's position in parent's coordinate system
409  QPointF itemPos;
410  switch (horizontalAlignment) {
412  itemPos.setX(x - w/2);
413  break;
415  itemPos.setX(x);
416  break;
418  itemPos.setX(x + w/2);
419  break;
420  }
421 
422  switch (verticalAlignment) {
424  itemPos.setY(y - h/2);
425  break;
427  itemPos.setY(y);
428  break;
430  itemPos.setY(y + h/2);
431  break;
432  }
433 
435  setPos(itemPos);
436  suppressItemChangeEvent = false;
437 
438  boundingRectangle.setX(-w/2);
439  boundingRectangle.setY(-h/2);
440  boundingRectangle.setWidth(w);
441  boundingRectangle.setHeight(h);
442 
443  updateBorder();
444 
445  emit q->changed();
446 }
447 
448 /*!
449  calculates the position of the label, when the position relative to the parent was specified (left, right, etc.)
450 */
452  //determine the parent item
453  QRectF parentRect;
454  QGraphicsItem* parent = parentItem();
455  if (parent) {
456  parentRect = parent->boundingRect();
457  } else {
458  if (!scene())
459  return;
460 
461  parentRect = scene()->sceneRect();
462  }
463 
466  position.point.setX( parentRect.x() );
468  position.point.setX( parentRect.x() + parentRect.width()/2 );
470  position.point.setX( parentRect.x() + parentRect.width() );
471  }
472 
475  position.point.setY( parentRect.y() );
477  position.point.setY( parentRect.y() + parentRect.height()/2 );
479  position.point.setY( parentRect.y() + parentRect.height() );
480  }
481 
482  emit q->positionChanged(position);
483 }
484 
485 /*!
486  updates the static text.
487  */
490  return;
491 
492  if (textWrapper.teXUsed) {
494  format.fontColor = fontColor;
496  format.fontSize = teXFont.pointSize();
497  format.fontFamily = teXFont.family();
498  format.dpi = teXImageResolution;
499  QFuture<QImage> future = QtConcurrent::run(TeXRenderer::renderImageLaTeX, textWrapper.text, &teXRenderSuccessful, format);
500  teXImageFutureWatcher.setFuture(future);
501 
502  //don't need to call retransorm() here since it is done in updateTeXImage
503  //when the asynchronous rendering of the image is finished.
504  } else {
505  staticText.setText(textWrapper.text);
506 
507  //the size of the label was most probably changed.
508  //call retransform() to recalculate the position and the bounding box of the label
509  retransform();
510  }
511 }
512 
514  teXImage = teXImageFutureWatcher.result();
515  retransform();
516  DEBUG("teXRenderSuccessful =" << teXRenderSuccessful);
518 }
519 
521  borderShapePath = QPainterPath();
522  switch (borderShape) {
524  break;
527  break;
529  const double xs = boundingRectangle.x();
530  const double ys = boundingRectangle.y();
531  const double w = boundingRectangle.width();
532  const double h = boundingRectangle.height();
533  borderShapePath.addEllipse(xs - 0.1 * w, ys - 0.1 * h, 1.2 * w, 1.2 * h);
534  break;
535  }
537  const double xs = boundingRectangle.x();
538  const double ys = boundingRectangle.y();
539  const double w = boundingRectangle.width();
540  const double h = boundingRectangle.height();
541  borderShapePath.moveTo(xs, ys);
542  borderShapePath.lineTo(xs + w, ys);
543  borderShapePath.quadTo(xs + w + h/2, ys + h/2, xs + w, ys + h);
544  borderShapePath.lineTo(xs, ys + h);
545  borderShapePath.quadTo(xs - h/2, ys + h/2, xs, ys);
546  break;
547  }
549  const double xs = boundingRectangle.x();
550  const double ys = boundingRectangle.y();
551  const double w = boundingRectangle.width();
552  const double h = boundingRectangle.height();
553  borderShapePath.moveTo(xs + h * 0.2, ys);
554  borderShapePath.lineTo(xs + w - h * 0.2, ys);
555  borderShapePath.quadTo(xs + w, ys, xs + w, ys + h * 0.2);
556  borderShapePath.lineTo(xs + w, ys + h - 0.2 * h);
557  borderShapePath.quadTo(xs + w, ys + h, xs + w - 0.2 * h, ys + h);
558  borderShapePath.lineTo(xs + 0.2 * h, ys + h);
559  borderShapePath.quadTo(xs, ys + h, xs, ys + h - 0.2 * h);
560  borderShapePath.lineTo(xs, ys + 0.2 * h);
561  borderShapePath.quadTo(xs, ys, xs + 0.2 * h, ys);
562  break;
563  }
565  const double xs = boundingRectangle.x();
566  const double ys = boundingRectangle.y();
567  const double w = boundingRectangle.width();
568  const double h = boundingRectangle.height();
569  borderShapePath.moveTo(xs, ys - 0.3 * h);
570  borderShapePath.lineTo(xs + w, ys - 0.3 * h);
571  borderShapePath.quadTo(xs + w, ys, xs + w + 0.3 * h, ys);
572  borderShapePath.lineTo(xs + w + 0.3 * h, ys + h);
573  borderShapePath.quadTo(xs + w, ys + h, xs + w, ys + h + 0.3 * h);
574  borderShapePath.lineTo(xs, ys + h + 0.3 * h);
575  borderShapePath.quadTo(xs, ys + h, xs - 0.3 * h, ys + h);
576  borderShapePath.lineTo(xs - 0.3 * h, ys);
577  borderShapePath.quadTo(xs, ys, xs, ys - 0.3 * h);
578  break;
579  }
581  const double xs = boundingRectangle.x();
582  const double ys = boundingRectangle.y();
583  const double w = boundingRectangle.width();
584  const double h = boundingRectangle.height();
585  borderShapePath.moveTo(xs - 0.2 * h, ys - 0.2 * h);
586  borderShapePath.quadTo(xs + w / 2, ys, xs + w + 0.2 * h, ys - 0.2 * h);
587  borderShapePath.quadTo(xs + w, ys + h / 2, xs + w + 0.2 * h, ys + h + 0.2 * h);
588  borderShapePath.quadTo(xs + w / 2, ys + h, xs - 0.2 * h, ys + h + 0.2 * h);
589  borderShapePath.quadTo(xs, ys + h / 2, xs - 0.2 * h, ys - 0.2 * h);
590  break;
591  }
593  const double xs = boundingRectangle.x();
594  const double ys = boundingRectangle.y();
595  const double w = boundingRectangle.width();
596  const double h = boundingRectangle.height();
597  borderShapePath.moveTo(xs, ys);
598  borderShapePath.lineTo(xs + w, ys);
599  borderShapePath.lineTo(xs + w, ys + h);
600  borderShapePath.lineTo(xs, ys + h);
601  borderShapePath.lineTo(xs, ys);
602  borderShapePath.lineTo(xs + 0.3 * h, ys - 0.2 * h);
603  borderShapePath.lineTo(xs + w + 0.3 * h, ys - 0.2 * h);
604  borderShapePath.lineTo(xs + w, ys);
605  borderShapePath.moveTo(xs + w, ys + h);
606  borderShapePath.lineTo(xs + w + 0.3 * h, ys + h - 0.2 * h);
607  borderShapePath.lineTo(xs + w + 0.3 * h, ys - 0.2 * h);
608  break;
609  }
611  const double xs = boundingRectangle.x();
612  const double ys = boundingRectangle.y();
613  const double w = boundingRectangle.width();
614  const double h = boundingRectangle.height();
615  borderShapePath.moveTo(xs + h * 0.2, ys);
616  borderShapePath.lineTo(xs + w / 2 - 0.2 * h, ys);
617  borderShapePath.lineTo(xs + w / 2, ys - 0.2 * h);
618  borderShapePath.lineTo(xs + w / 2 + 0.2 * h, ys);
619  borderShapePath.lineTo(xs + w - h * 0.2, ys);
620  borderShapePath.quadTo(xs + w, ys, xs + w, ys + h * 0.2);
621  borderShapePath.lineTo(xs + w, ys + h - 0.2 * h);
622  borderShapePath.quadTo(xs + w, ys + h, xs + w - 0.2 * h, ys + h);
623  borderShapePath.lineTo(xs + 0.2 * h, ys + h);
624  borderShapePath.quadTo(xs, ys + h, xs, ys + h - 0.2 * h);
625  borderShapePath.lineTo(xs, ys + 0.2 * h);
626  borderShapePath.quadTo(xs, ys, xs + 0.2 * h, ys);
627  break;
628  }
630  const double xs = boundingRectangle.x();
631  const double ys = boundingRectangle.y();
632  const double w = boundingRectangle.width();
633  const double h = boundingRectangle.height();
634  borderShapePath.moveTo(xs +h * 0.2, ys);
635  borderShapePath.lineTo(xs + w - h * 0.2, ys);
636  borderShapePath.quadTo(xs + w, ys, xs + w, ys + h * 0.2);
637  borderShapePath.lineTo(xs + w, ys + h - 0.2 * h);
638  borderShapePath.quadTo(xs + w, ys + h, xs + w - 0.2 * h, ys + h);
639  borderShapePath.lineTo(xs + w / 2 + 0.2 * h, ys + h);
640  borderShapePath.lineTo(xs + w / 2, ys + h + 0.2 * h);
641  borderShapePath.lineTo(xs + w / 2 - 0.2 * h, ys + h);
642  borderShapePath.lineTo(xs + 0.2 * h, ys + h);
643  borderShapePath.quadTo(xs, ys + h, xs, ys + h - 0.2 * h);
644  borderShapePath.lineTo(xs, ys + 0.2 * h);
645  borderShapePath.quadTo(xs, ys, xs + 0.2 * h, ys);
646  break;
647  }
649  const double xs = boundingRectangle.x();
650  const double ys = boundingRectangle.y();
651  const double w = boundingRectangle.width();
652  const double h = boundingRectangle.height();
653  borderShapePath.moveTo(xs + h*0.2, ys);
654  borderShapePath.lineTo(xs + w - h * 0.2, ys);
655  borderShapePath.quadTo(xs + w, ys, xs + w, ys + h * 0.2);
656  borderShapePath.lineTo(xs + w, ys + h - 0.2 * h);
657  borderShapePath.quadTo(xs + w, ys + h, xs + w - 0.2 * h, ys + h);
658  borderShapePath.lineTo(xs + 0.2 * h, ys + h);
659  borderShapePath.quadTo(xs, ys + h, xs, ys + h - 0.2 * h);
660  borderShapePath.lineTo(xs, ys + h / 2 + 0.2 * h);
661  borderShapePath.lineTo(xs - 0.2 * h, ys + h / 2);
662  borderShapePath.lineTo(xs, ys + h / 2 - 0.2 * h);
663  borderShapePath.lineTo(xs, ys + 0.2 * h);
664  borderShapePath.quadTo(xs, ys, xs + 0.2 * h, ys);
665  break;
666  }
668  const double xs = boundingRectangle.x();
669  const double ys = boundingRectangle.y();
670  const double w = boundingRectangle.width();
671  const double h = boundingRectangle.height();
672  borderShapePath.moveTo(xs + h * 0.2, ys);
673  borderShapePath.lineTo(xs + w - h * 0.2, ys);
674  borderShapePath.quadTo(xs + w, ys, xs + w, ys + h * 0.2);
675  borderShapePath.lineTo(xs + w, ys + h / 2 - 0.2 * h);
676  borderShapePath.lineTo(xs + w + 0.2 * h, ys + h / 2);
677  borderShapePath.lineTo(xs + w, ys + h / 2 + 0.2 * h);
678  borderShapePath.lineTo(xs + w, ys + h - 0.2 * h);
679  borderShapePath.quadTo(xs + w, ys + h, xs + w - 0.2 * h, ys + h);
680  borderShapePath.lineTo(xs + 0.2 * h, ys + h);
681  borderShapePath.quadTo(xs, ys + h, xs, ys + h - 0.2 * h);
682  borderShapePath.lineTo(xs, ys + 0.2 * h);
683  borderShapePath.quadTo(xs, ys, xs + 0.2 * h, ys);
684  break;
685  }
686  }
687 
689 }
690 
692  bool oldValue = isVisible();
693 
694  //When making a graphics item invisible, it gets deselected in the scene.
695  //In this case we don't want to deselect the item in the project explorer.
696  //We need to supress the deselection in the view.
697  auto* worksheet = static_cast<Worksheet*>(q->parent(AspectType::Worksheet));
698  worksheet->suppressSelectionChangedEvent(true);
699  setVisible(on);
700  worksheet->suppressSelectionChangedEvent(false);
701 
702  emit q->changed();
703  emit q->visibleChanged(on);
704  return oldValue;
705 }
706 
707 /*!
708  Returns the outer bounds of the item as a rectangle.
709  */
712 }
713 
714 /*!
715  Returns the shape of this item as a QPainterPath in local coordinates.
716 */
717 QPainterPath TextLabelPrivate::shape() const {
718  return labelShape;
719 }
720 
721 /*!
722  recalculates the outer bounds and the shape of the label.
723 */
725  prepareGeometryChange();
726 
727  QMatrix matrix;
728  matrix.rotate(-rotationAngle);
729  labelShape = QPainterPath();
732  transformedBoundingRectangle = matrix.mapRect(labelShape.boundingRect());
733  } else {
734  labelShape.addRect(boundingRectangle);
736  }
737 
738  labelShape = matrix.map(labelShape);
739 }
740 
741 void TextLabelPrivate::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
742  Q_UNUSED(option)
743  Q_UNUSED(widget)
744 
745  if (positionInvalid || textWrapper.text.isEmpty())
746  return;
747 
748  painter->save();
749  painter->rotate(-rotationAngle);
750 
751  //draw the text
752  if (textWrapper.teXUsed) {
753  if (boundingRect().width() != 0.0 && boundingRect().height() != 0.0)
754  painter->drawImage(boundingRect(), teXImage);
755  } else {
756  // don't set pen color, the color is already in the HTML code
757  //painter->setPen(fontColor);
758  painter->scale(scaleFactor, scaleFactor);
759  qreal w = staticText.size().width();
760  qreal h = staticText.size().height();
761  //staticText.setPerformanceHint(QStaticText::AggressiveCaching);
762  //QDEBUG(Q_FUNC_INFO << ", Drawing text:" << staticText.text())
763  painter->drawStaticText(QPointF(-w/2., -h/2.), staticText);
764  }
765  painter->restore();
766 
767  //draw the border
769  painter->save();
770  painter->setPen(borderPen);
771  painter->setOpacity(borderOpacity);
772 
773  painter->rotate(-rotationAngle);
774  painter->drawPath(borderShapePath);
775  painter->restore();
776  }
777 
778  if (m_hovered && !isSelected() && !m_printing) {
779  painter->setPen(QPen(QApplication::palette().color(QPalette::Shadow), 2, Qt::SolidLine));
780  painter->drawPath(labelShape);
781  }
782 
783  if (isSelected() && !m_printing) {
784  painter->setPen(QPen(QApplication::palette().color(QPalette::Highlight), 2, Qt::SolidLine));
785  painter->drawPath(labelShape);
786  }
787 }
788 
789 QVariant TextLabelPrivate::itemChange(GraphicsItemChange change, const QVariant &value) {
791  return value;
792 
793  if (change == QGraphicsItem::ItemPositionChange) {
794  //convert item's center point in parent's coordinates
795  TextLabel::PositionWrapper tempPosition;
796  tempPosition.point = positionFromItemPosition(value.toPointF());
799 
800  //emit the signals in order to notify the UI.
801  //we don't set the position related member variables during the mouse movements.
802  //this is done on mouse release events only.
803  emit q->positionChanged(tempPosition);
804  }
805 
806  return QGraphicsItem::itemChange(change, value);
807 }
808 
809 void TextLabelPrivate::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) {
810  //convert position of the item in parent coordinates to label's position
811  QPointF point = positionFromItemPosition(pos());
812  if (point != position.point) {
813  //position was changed -> set the position related member variables
814  suppressRetransform = true;
815  TextLabel::PositionWrapper tempPosition;
816  tempPosition.point = point;
819  q->setPosition(tempPosition);
820  suppressRetransform = false;
821  }
822 
823  QGraphicsItem::mouseReleaseEvent(event);
824 }
825 
826 void TextLabelPrivate::keyPressEvent(QKeyEvent* event) {
827  if (event->key() == Qt::Key_Left || event->key() == Qt::Key_Right
828  || event->key() == Qt::Key_Up ||event->key() == Qt::Key_Down) {
829  const int delta = 5;
830  QPointF point = positionFromItemPosition(pos());
832 
833  if (event->key() == Qt::Key_Left) {
834  point.setX(point.x() - delta);
837  } else if (event->key() == Qt::Key_Right) {
838  point.setX(point.x() + delta);
841  } else if (event->key() == Qt::Key_Up) {
842  point.setY(point.y() - delta);
845  } else if (event->key() == Qt::Key_Down) {
846  point.setY(point.y() + delta);
849  }
850 
851  tempPosition.point = point;
852  q->setPosition(tempPosition);
853  }
854 
855  QGraphicsItem::keyPressEvent(event);
856 }
857 
858 /*!
859  * converts label's position to GraphicsItem's position.
860  */
862  double x = itemPos.x();
863  double y = itemPos.y();
864  double w, h;
865  QPointF tmpPosition;
866  if (textWrapper.teXUsed) {
867  w = teXImage.width()*scaleFactor;
868  h = teXImage.height()*scaleFactor;
869  } else {
870  w = staticText.size().width()*scaleFactor;
871  h = staticText.size().height()*scaleFactor;
872  }
873 
874  //depending on the alignment, calculate the new position
875  switch (horizontalAlignment) {
877  tmpPosition.setX(x + w/2);
878  break;
880  tmpPosition.setX(x);
881  break;
883  tmpPosition.setX(x - w/2);
884  break;
885  }
886 
887  switch (verticalAlignment) {
889  tmpPosition.setY(y + h/2);
890  break;
892  tmpPosition.setY(y);
893  break;
895  tmpPosition.setY(y - h/2);
896  break;
897  }
898 
899  return tmpPosition;
900 }
901 
902 void TextLabelPrivate::contextMenuEvent(QGraphicsSceneContextMenuEvent* event) {
903  q->createContextMenu()->exec(event->screenPos());
904 }
905 
906 void TextLabelPrivate::hoverEnterEvent(QGraphicsSceneHoverEvent*) {
907  if (!isSelected()) {
908  m_hovered = true;
909  emit q->hovered();
910  update();
911  }
912 }
913 
914 void TextLabelPrivate::hoverLeaveEvent(QGraphicsSceneHoverEvent*) {
915  if (m_hovered) {
916  m_hovered = false;
917  emit q->unhovered();
918  update();
919  }
920 }
921 
922 //##############################################################################
923 //################## Serialization/Deserialization ###########################
924 //##############################################################################
925 //! Save as XML
926 void TextLabel::save(QXmlStreamWriter* writer) const {
927  Q_D(const TextLabel);
928 
929  writer->writeStartElement( "textLabel" );
930  writeBasicAttributes(writer);
931  writeCommentElement(writer);
932 
933  //geometry
934  writer->writeStartElement( "geometry" );
935  writer->writeAttribute( "x", QString::number(d->position.point.x()) );
936  writer->writeAttribute( "y", QString::number(d->position.point.y()) );
937  writer->writeAttribute( "horizontalPosition", QString::number(static_cast<int>(d->position.horizontalPosition)) );
938  writer->writeAttribute( "verticalPosition", QString::number(static_cast<int>(d->position.verticalPosition)) );
939  writer->writeAttribute( "horizontalAlignment", QString::number(static_cast<int>(d->horizontalAlignment)) );
940  writer->writeAttribute( "verticalAlignment", QString::number(static_cast<int>(d->verticalAlignment)) );
941  writer->writeAttribute( "rotationAngle", QString::number(d->rotationAngle) );
942  writer->writeAttribute( "visible", QString::number(d->isVisible()) );
943  writer->writeEndElement();
944 
945  writer->writeStartElement( "text" );
946  writer->writeCharacters( d->textWrapper.text );
947  writer->writeEndElement();
948 
949  writer->writeStartElement( "format" );
950  writer->writeAttribute( "teXUsed", QString::number(d->textWrapper.teXUsed) );
951  WRITE_QFONT(d->teXFont);
952  writer->writeAttribute( "fontColor_r", QString::number(d->fontColor.red()) );
953  writer->writeAttribute( "fontColor_g", QString::number(d->fontColor.green()) );
954  writer->writeAttribute( "fontColor_b", QString::number(d->fontColor.blue()) );
955  writer->writeEndElement();
956 
957  //border
958  writer->writeStartElement("border");
959  writer->writeAttribute("borderShape", QString::number(static_cast<int>(d->borderShape)));
960  WRITE_QPEN(d->borderPen);
961  writer->writeAttribute("borderOpacity", QString::number(d->borderOpacity));
962  writer->writeEndElement();
963 
964  if (d->textWrapper.teXUsed) {
965  writer->writeStartElement("teXImage");
966  QByteArray ba;
967  QBuffer buffer(&ba);
968  buffer.open(QIODevice::WriteOnly);
969  d->teXImage.save(&buffer, "PNG");
970  writer->writeCharacters(ba.toBase64());
971  writer->writeEndElement();
972  }
973 
974  writer->writeEndElement(); // close "textLabel" section
975 }
976 
977 //! Load from XML
978 bool TextLabel::load(XmlStreamReader* reader, bool preview) {
979  if (!readBasicAttributes(reader))
980  return false;
981 
982  Q_D(TextLabel);
983  KLocalizedString attributeWarning = ki18n("Attribute '%1' missing or empty, default value is used");
984  QXmlStreamAttributes attribs;
985  QString str;
986  bool teXImageFound = false;
987 
988  while (!reader->atEnd()) {
989  reader->readNext();
990  if (reader->isEndElement() && reader->name() == "textLabel")
991  break;
992 
993  if (!reader->isStartElement())
994  continue;
995 
996  if (!preview && reader->name() == "comment") {
997  if (!readCommentElement(reader)) return false;
998  } else if (!preview && reader->name() == "geometry") {
999  attribs = reader->attributes();
1000 
1001  str = attribs.value("x").toString();
1002  if (str.isEmpty())
1003  reader->raiseWarning(attributeWarning.subs("x").toString());
1004  else
1005  d->position.point.setX(str.toDouble());
1006 
1007  str = attribs.value("y").toString();
1008  if (str.isEmpty())
1009  reader->raiseWarning(attributeWarning.subs("y").toString());
1010  else
1011  d->position.point.setY(str.toDouble());
1012 
1013  READ_INT_VALUE("horizontalPosition", position.horizontalPosition, WorksheetElement::HorizontalPosition);
1014  READ_INT_VALUE("verticalPosition", position.verticalPosition, WorksheetElement::VerticalPosition);
1015  READ_INT_VALUE("horizontalAlignment", horizontalAlignment, WorksheetElement::HorizontalAlignment);
1016  READ_INT_VALUE("verticalAlignment", verticalAlignment, WorksheetElement::VerticalAlignment);
1017  READ_DOUBLE_VALUE("rotationAngle", rotationAngle);
1018 
1019  str = attribs.value("visible").toString();
1020  if (str.isEmpty())
1021  reader->raiseWarning(attributeWarning.subs("visible").toString());
1022  else
1023  d->setVisible(str.toInt());
1024  } else if (!preview && reader->name() == "text") {
1025  d->textWrapper.text = reader->readElementText();
1026  } else if (!preview && reader->name() == "format") {
1027  attribs = reader->attributes();
1028 
1029  READ_INT_VALUE("teXUsed", textWrapper.teXUsed, bool);
1030  READ_QFONT(d->teXFont);
1031 
1032  str = attribs.value("fontColor_r").toString();
1033  if (str.isEmpty())
1034  reader->raiseWarning(attributeWarning.subs("fontColor_r").toString());
1035  else
1036  d->fontColor.setRed( str.toInt() );
1037 
1038  str = attribs.value("fontColor_g").toString();
1039  if (str.isEmpty())
1040  reader->raiseWarning(attributeWarning.subs("fontColor_g").toString());
1041  else
1042  d->fontColor.setGreen( str.toInt() );
1043 
1044  str = attribs.value("fontColor_b").toString();
1045  if (str.isEmpty())
1046  reader->raiseWarning(attributeWarning.subs("fontColor_b").toString());
1047  else
1048  d->fontColor.setBlue( str.toInt() );
1049  } else if (!preview && reader->name() == "border") {
1050  attribs = reader->attributes();
1051  READ_INT_VALUE("borderShape", borderShape, BorderShape);
1052  READ_QPEN(d->borderPen);
1053  READ_DOUBLE_VALUE("borderOpacity", borderOpacity);
1054  } else if (!preview && reader->name() == "teXImage") {
1055  reader->readNext();
1056  QString content = reader->text().toString().trimmed();
1057  QByteArray ba = QByteArray::fromBase64(content.toLatin1());
1058  teXImageFound = d->teXImage.loadFromData(ba);
1059  } else { // unknown element
1060  reader->raiseWarning(i18n("unknown element '%1'", reader->name().toString()));
1061  if (!reader->skipToEndElement()) return false;
1062  }
1063  }
1064 
1065  if (preview)
1066  return true;
1067 
1068  //in case we use latex and the image was stored (older versions of LabPlot didn't save the image)and loaded,
1069  //we just need to retransform.
1070  //otherwise, we set the static text and retransform in updateText()
1071  if ( !(d->textWrapper.teXUsed && teXImageFound) )
1072  d->updateText();
1073  else
1074  retransform();
1075 
1076  return true;
1077 }
1078 
1079 //##############################################################################
1080 //######################### Theme management ##################################
1081 //##############################################################################
1082 void TextLabel::loadThemeConfig(const KConfig& config) {
1083  Q_D(TextLabel);
1084 
1085  KConfigGroup group = config.group("Label");
1086  d->fontColor = group.readEntry("FontColor", QColor(Qt::black)); // used when it's latex text
1087  d->backgroundColor = group.readEntry("BackgroundColor", QColor(Qt::white)); // used when it's latex text
1088 
1089  if (!d->textWrapper.teXUsed && !d->textWrapper.text.isEmpty()) {
1090  // TODO: Replace QTextEdit by QTextDocument, because this does not contain the graphical stuff
1091  // to set the color in a html text, a qTextEdit must be used
1092  QTextEdit te;
1093  te.setHtml(d->textWrapper.text);
1094  te.selectAll();
1095  te.setTextColor(d->fontColor);
1096  //te.setTextBackgroundColor(backgroundColor); // for plain text no background color supported, due to bug https://bugreports.qt.io/browse/QTBUG-25420
1097 
1098  // update the text. also in the Widget to which is connected
1099  TextWrapper wrapper(te.toHtml(), false, true);
1100  setText(wrapper);
1101  }
1102 
1103  // otherwise when changing theme while the textlabel dock is visible, the
1104  // color comboboxes do not change the color
1105  backgroundColorChanged(d->backgroundColor);
1106  fontColorChanged(d->fontColor);
1107 
1108  group = config.group("CartesianPlot");
1109  QPen pen = this->borderPen();
1110  pen.setColor(group.readEntry("BorderColor", pen.color()));
1111  pen.setStyle((Qt::PenStyle)(group.readEntry("BorderStyle", (int) pen.style())));
1112  pen.setWidthF(group.readEntry("BorderWidth", pen.widthF()));
1113  this->setBorderPen(pen);
1114  this->setBorderOpacity(group.readEntry("BorderOpacity", this->borderOpacity()));
1115 }
1116 
1117 void TextLabel::saveThemeConfig(const KConfig& config) {
1118  KConfigGroup group = config.group("Label");
1119  //TODO
1120 // group.writeEntry("TeXFontColor", (QColor) this->fontColor());
1121 }
AspectType
static const QRgb white
Definition: ImageEditor.cpp:37
static const QRgb black
Definition: ImageEditor.cpp:38
STD_SWAP_METHOD_SETTER_CMD_IMPL_F(TextLabel, SetVisible, bool, swapVisible, retransform)
CLASS_SHARED_D_READER_IMPL(TextLabel, QColor, fontColor, fontColor)
STD_SETTER_CMD_IMPL_F_S(TextLabel, SetText, TextLabel::TextWrapper, textWrapper, updateText)
BASIC_SHARED_D_READER_IMPL(TextLabel, WorksheetElement::HorizontalAlignment, horizontalAlignment, horizontalAlignment)
bool readCommentElement(XmlStreamReader *)
Load comment from an XML element.
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.
bool readBasicAttributes(XmlStreamReader *)
Load name and creation time from XML.
void writeCommentElement(QXmlStreamWriter *) const
Save the comment to XML.
AbstractAspectPrivate * d
static QImage renderImageLaTeX(const QString &, bool *success, const TeXRenderer::Formatting &)
Definition: TeXRenderer.cpp:51
void hoverLeaveEvent(QGraphicsSceneHoverEvent *) override
Definition: TextLabel.cpp:914
WorksheetElement::HorizontalAlignment horizontalAlignment
void hoverEnterEvent(QGraphicsSceneHoverEvent *) override
Definition: TextLabel.cpp:906
virtual void recalcShapeAndBoundingRect()
Definition: TextLabel.cpp:724
WorksheetElement::VerticalAlignment verticalAlignment
void contextMenuEvent(QGraphicsSceneContextMenuEvent *) override
Definition: TextLabel.cpp:902
void updatePosition()
Definition: TextLabel.cpp:451
TextLabelPrivate(TextLabel *)
Definition: TextLabel.cpp:369
QPainterPath borderShapePath
TextLabel::BorderShape borderShape
void keyPressEvent(QKeyEvent *) override
Definition: TextLabel.cpp:826
QPointF positionFromItemPosition(QPointF)
Definition: TextLabel.cpp:861
QPainterPath labelShape
void updateTeXImage()
Definition: TextLabel.cpp:513
QRectF transformedBoundingRectangle
QFutureWatcher< QImage > teXImageFutureWatcher
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *widget=nullptr) override
Definition: TextLabel.cpp:741
TextLabel::TextWrapper textWrapper
QRectF boundingRect() const override
Definition: TextLabel.cpp:710
QStaticText staticText
void mouseReleaseEvent(QGraphicsSceneMouseEvent *) override
Definition: TextLabel.cpp:809
QString name() const
Definition: TextLabel.cpp:377
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override
Definition: TextLabel.cpp:789
TextLabel *const q
QPainterPath shape() const override
Definition: TextLabel.cpp:717
WorksheetElement::PositionWrapper position
bool swapVisible(bool on)
Definition: TextLabel.cpp:691
A label supporting rendering of html- and tex-formatted texts.
Definition: TextLabel.h:44
void init()
Definition: TextLabel.cpp:80
void changed()
QAction * visibilityAction
Definition: TextLabel.h:130
void loadThemeConfig(const KConfig &) override
Definition: TextLabel.cpp:1082
TextLabel(const QString &name, Type type=Type::General)
Definition: TextLabel.cpp:64
Type type() const
Definition: TextLabel.cpp:76
void saveThemeConfig(const KConfig &) override
Definition: TextLabel.cpp:1117
Type m_type
Definition: TextLabel.h:129
void setParentGraphicsItem(QGraphicsItem *)
Definition: TextLabel.cpp:160
void setPositionInvalid(bool)
Definition: TextLabel.cpp:287
bool isVisible() const override
Return whether the element is (at least) partially visible.
Definition: TextLabel.cpp:343
void setVisible(bool on) override
Show/hide the element.
Definition: TextLabel.cpp:338
QMenu * createContextMenu() override
Return a new context menu.
Definition: TextLabel.cpp:204
QIcon icon() const override
Definition: TextLabel.cpp:200
~TextLabel() override
void visibilityChanged()
Definition: TextLabel.cpp:361
void teXImageUpdated(bool)
void visibleChanged(bool)
QGraphicsItem * graphicsItem() const override
Return the graphics item representing this element.
Definition: TextLabel.cpp:156
void backgroundColorChanged(const QColor)
bool load(XmlStreamReader *, bool preview) override
Load from XML.
Definition: TextLabel.cpp:978
void updateTeXImage()
Definition: TextLabel.cpp:353
void handleResize(double horizontalRatio, double verticalRatio, bool pageResize) override
Definition: TextLabel.cpp:171
void save(QXmlStreamWriter *) const override
Save as XML.
Definition: TextLabel.cpp:926
void retransform() override
Tell the element to newly transform its graphics item into its coordinate system.
Definition: TextLabel.cpp:166
void positionChanged(const WorksheetElement::PositionWrapper &)
void fontColorChanged(const QColor)
TextLabelPrivate *const d_ptr
Definition: TextLabel.h:122
void setPosition(QPointF)
Definition: TextLabel.cpp:265
void setPrinting(bool) override
Switches the printing mode on/off.
Definition: TextLabel.cpp:348
Base class for all Worksheet children.
static QPainterPath shapeFromPath(const QPainterPath &, const QPen &)
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
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 STDSTRING(qstr)
Definition: macros.h:67
#define DEBUG(x)
Definition: macros.h:50
#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 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