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)  

Datapicker.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  File : Datapicker.cpp
3  Project : LabPlot
4  Description : Datapicker
5  --------------------------------------------------------------------
6  Copyright : (C) 2015 by Ankit Wagadre (wagadre.ankit@gmail.com)
7  Copyright : (C) 2015-2019 Alexander Semke (alexander.semke@web.de)
8 
9  ***************************************************************************/
10 /***************************************************************************
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  * This program is distributed in the hope that it will be useful, *
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
20  * GNU General Public License for more details. *
21  * *
22  * You should have received a copy of the GNU General Public License *
23  * along with this program; if not, write to the Free Software *
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
25  * Boston, MA 02110-1301 USA *
26  * *
27  ***************************************************************************/
28 
29 #include "Datapicker.h"
37 
38 #include <QGraphicsScene>
39 #include "QIcon"
40 #include <KLocalizedString>
41 
42 /**
43  * \class Datapicker
44  * \brief Top-level container for DatapickerCurve and DatapickerImage.
45  * \ingroup backend
46  */
47 Datapicker::Datapicker(const QString& name, const bool loading)
48 : AbstractPart(name, AspectType::Datapicker), m_transform(new Transform())
49 {
52 
53  if (!loading)
54  init();
55 }
56 
58  delete m_transform;
59 }
60 
62  m_image = new DatapickerImage(i18n("Plot"));
63  m_image->setHidden(true);
64  setUndoAware(false);
66  setUndoAware(true);
67 
69 }
70 
71 /*!
72  Returns an icon to be used in the project explorer.
73 */
74 QIcon Datapicker::icon() const {
75  return QIcon::fromTheme("color-picker-black");
76 }
77 
78 /*!
79  * Returns a new context menu. The caller takes ownership of the menu.
80  */
82  QMenu* menu = AbstractPart::createContextMenu();
83  Q_ASSERT(menu);
85  return menu;
86 }
87 
88 QWidget* Datapicker::view() const {
89  if (!m_partView) {
90  m_view = new DatapickerView(const_cast<Datapicker*>(this));
92  }
93  return m_partView;
94 }
95 
96 
97 bool Datapicker::exportView() const {
99  bool ret;
100  if (s)
101  ret = s->exportView();
102  else
103  ret = m_image->exportView();
104  return ret;
105 }
106 
109  bool ret;
110  if (s)
111  ret = s->printView();
112  else
113  ret = m_image->printView();
114  return ret;
115 }
116 
119  bool ret;
120  if (s)
121  ret = s->printPreview();
122  else
123  ret = m_image->printPreview();
124  return ret;
125 }
126 
128  return m_activeCurve;
129 }
130 
132  if (!m_view)
133  return nullptr;
134 
135  const int index = m_view->currentIndex();
136  if (index > 0) {
137  auto* curve = child<DatapickerCurve>(index-1);
138  return curve->child<Spreadsheet>(0);
139  }
140  return nullptr;
141 }
142 
144  return m_image;
145 }
146 
147 /*!
148  this slot is called when a datapicker child is selected in the project explorer.
149  emits \c datapickerItemSelected() to forward this event to the \c DatapickerView
150  in order to select the corresponding tab.
151  */
153  Q_ASSERT(aspect);
154  m_activeCurve = dynamic_cast<DatapickerCurve*>(const_cast<AbstractAspect*>(aspect));
155 
156  int index = -1;
157  if (m_activeCurve) {
158  //if one of the curves is currently selected, select the image with the plot (the very first child)
159  index = 0;
160  emit statusInfo(i18n("%1, active curve \"%2\"", this->name(), m_activeCurve->name()));
161  emit requestUpdateActions();
162  } else if (aspect) {
163  const auto* curve = aspect->ancestor<const DatapickerCurve>();
164  index = indexOfChild<AbstractAspect>(curve);
165  ++index; //+1 because of the hidden plot image being the first child and shown in the first tab in the view
166  }
167 
168  emit datapickerItemSelected(index);
169 }
170 
171 /*!
172  this slot is called when a worksheet element is deselected in the project explorer.
173  */
175  Q_UNUSED(aspect);
176 }
177 
178 /*!
179  * Emits the signal to select or to deselect the datapicker item (spreadsheet or image) with the index \c index
180  * in the project explorer, if \c selected=true or \c selected=false, respectively.
181  * The signal is handled in \c AspectTreeModel and forwarded to the tree view in \c ProjectExplorer.
182  * This function is called in \c DatapickerView when the current tab was changed
183  */
184 void Datapicker::setChildSelectedInView(int index, bool selected) {
185  //select/deselect the datapicker itself if the first tab "representing" the plot image and the curves was selected in the view
186  if (index == 0) {
187  if (selected)
188  emit childAspectSelectedInView(this);
189  else {
190  emit childAspectDeselectedInView(this);
191 
192  //deselect also all curves (they don't have any tab index in the view) that were potentially selected before
193  for (const auto* curve : children<const DatapickerCurve>())
194  emit childAspectDeselectedInView(curve);
195  }
196 
197  return;
198  }
199 
200  --index; //-1 because of the first tab in the view being reserved for the plot image and curves
201 
202  //select/deselect the data spreadhseets
203  auto spreadsheets = children<const Spreadsheet>(ChildIndexFlag::Recursive);
204  const AbstractAspect* aspect = spreadsheets.at(index);
205  if (selected) {
206  emit childAspectSelectedInView(aspect);
207 
208  //deselect the datapicker in the project explorer, if a child (spreadsheet or image) was selected.
209  //prevents unwanted multiple selection with datapicker if it was selected before.
210  emit childAspectDeselectedInView(this);
211  } else {
212  emit childAspectDeselectedInView(aspect);
213 
214  //deselect also all children that were potentially selected before (columns of a spreadsheet)
215  for (const auto* child : aspect->children<const AbstractAspect>())
217  }
218 }
219 
220 /*!
221  Selects or deselects the datapicker or its current active curve in the project explorer.
222  This function is called in \c DatapickerImageView.
223 */
224 void Datapicker::setSelectedInView(const bool b) {
225  if (b)
226  emit childAspectSelectedInView(this);
227  else
228  emit childAspectDeselectedInView(this);
229 }
230 
231 void Datapicker::addNewPoint(QPointF pos, AbstractAspect* parentAspect) {
233 
234  auto* newPoint = new DatapickerPoint(i18n("Point %1", points.count() + 1));
235  newPoint->setPosition(pos);
236  newPoint->setHidden(true);
237 
238  beginMacro(i18n("%1: add %2", parentAspect->name(), newPoint->name()));
239  parentAspect->addChild(newPoint);
240  newPoint->retransform();
241 
242  auto* datapickerCurve = static_cast<DatapickerCurve*>(parentAspect);
243  if (m_image == parentAspect) {
244  DatapickerImage::ReferencePoints axisPoints = m_image->axisPoints();
245  axisPoints.scenePos[points.count()].setX(pos.x());
246  axisPoints.scenePos[points.count()].setY(pos.y());
247  m_image->setAxisPoints(axisPoints);
248  } else if (datapickerCurve) {
249  newPoint->initErrorBar(datapickerCurve->curveErrorTypes());
250  datapickerCurve->updatePoint(newPoint);
251  }
252 
253  endMacro();
254  emit requestUpdateActions();
255 }
256 
257 QVector3D Datapicker::mapSceneToLogical(QPointF point) const {
258  return m_transform->mapSceneToLogical(point, m_image->axisPoints());
259 }
260 
261 QVector3D Datapicker::mapSceneLengthToLogical(QPointF point) const {
262  return m_transform->mapSceneLengthToLogical(point, m_image->axisPoints());
263 }
264 
266  const auto* curve = qobject_cast<const DatapickerCurve*>(aspect);
267  if (curve) {
268  //clear scene
269  auto points = curve->children<DatapickerPoint>(ChildIndexFlag::IncludeHidden);
270  for (auto* point : points)
272 
273  if (curve == m_activeCurve) {
274  m_activeCurve = nullptr;
275  emit statusInfo(QString());
276  }
277  } else
279 
280  emit requestUpdateActions();
281 }
282 
284  const auto* addedPoint = qobject_cast<const DatapickerPoint*>(aspect);
285  const auto* curve = qobject_cast<const DatapickerCurve*>(aspect);
286  if (addedPoint)
287  handleChildAspectAdded(addedPoint);
288  else if (curve) {
290  auto points = curve->children<DatapickerPoint>(ChildIndexFlag::IncludeHidden);
291  for (auto* point : points)
292  handleChildAspectAdded(point);
293  } else
294  return;
295 
296  qreal zVal = 0;
298  for (auto* point : points)
299  point->graphicsItem()->setZValue(zVal++);
300 
301  for (const auto* curve : children<DatapickerCurve>()) {
302  for (auto* point : curve->children<DatapickerPoint>(ChildIndexFlag::IncludeHidden))
303  point->graphicsItem()->setZValue(zVal++);
304  }
305 
306  emit requestUpdateActions();
307 }
308 
310  const auto* removedPoint = qobject_cast<const DatapickerPoint*>(aspect);
311  if (removedPoint) {
312  QGraphicsItem* item = removedPoint->graphicsItem();
313  Q_ASSERT(item != nullptr);
314  Q_ASSERT(m_image != nullptr);
315  m_image->scene()->removeItem(item);
316  }
317 }
318 
320  const auto* addedPoint = qobject_cast<const DatapickerPoint*>(aspect);
321  if (addedPoint) {
322  QGraphicsItem* item = addedPoint->graphicsItem();
323  Q_ASSERT(item != nullptr);
324  Q_ASSERT(m_image != nullptr);
325  m_image->scene()->addItem(item);
326  }
327 }
328 
329 //##############################################################################
330 //################## Serialization/Deserialization ###########################
331 //##############################################################################
332 
333 //! Save as XML
334 void Datapicker::save(QXmlStreamWriter* writer) const {
335  writer->writeStartElement( "datapicker" );
336  writeBasicAttributes(writer);
337  writeCommentElement(writer);
338 
339  //serialize all children
340  for (auto* child : children<AbstractAspect>(ChildIndexFlag::IncludeHidden))
341  child->save(writer);
342 
343  writer->writeEndElement(); // close "datapicker" section
344 }
345 
346 //! Load from XML
347 bool Datapicker::load(XmlStreamReader* reader, bool preview) {
348  if (!readBasicAttributes(reader))
349  return false;
350 
351  while (!reader->atEnd()) {
352  reader->readNext();
353  if (reader->isEndElement() && reader->name() == "datapicker")
354  break;
355 
356  if (!reader->isStartElement())
357  continue;
358 
359  if (reader->name() == "comment") {
360  if (!readCommentElement(reader))
361  return false;
362  } else if (reader->name() == "datapickerImage") {
363  auto* plot = new DatapickerImage(i18n("Plot"), true);
364  if (!plot->load(reader, preview)) {
365  delete plot;
366  return false;
367  } else {
368  plot->setHidden(true);
369  addChild(plot);
370  m_image = plot;
371  }
372  } else if (reader->name() == "datapickerCurve") {
373  auto* curve = new DatapickerCurve(QString());
374  if (!curve->load(reader, preview)) {
375  delete curve;
376  return false;
377  } else
378  addChild(curve);
379  } else { // unknown element
380  reader->raiseWarning(i18n("unknown datapicker element '%1'", reader->name().toString()));
381  if (!reader->skipToEndElement()) return false;
382  }
383  }
384 
385  for (auto* aspect : children<AbstractAspect>(ChildIndexFlag::IncludeHidden)) {
386  for (auto* point : aspect->children<DatapickerPoint>(ChildIndexFlag::IncludeHidden))
387  handleAspectAdded(point);
388  }
389 
390  return true;
391 }
AspectType
Base class of all persistent objects in a Project.
void setUndoAware(bool)
void aspectAdded(const AbstractAspect *)
Emitted after a new Aspect has been added to the tree.
bool readCommentElement(XmlStreamReader *)
Load comment from an XML element.
@ Recursive
Recursively handle all descendents, not just immediate children.
@ IncludeHidden
Include aspects marked as "hidden" in numbering or listing children.
void addChild(AbstractAspect *)
Add the given Aspect to my list of children.
void childAspectSelectedInView(const AbstractAspect *)
void childAspectDeselectedInView(const AbstractAspect *)
void aspectAboutToBeRemoved(const AbstractAspect *)
Emitted before an aspect is removed from its parent.
T * ancestor() const
Return the closest ancestor of class T (or NULL if none found).
QString name() const
void statusInfo(const QString &)
Emitted whenever some aspect in the tree wants to give status information to the user.
void writeBasicAttributes(QXmlStreamWriter *) const
Save name and creation time to XML.
void selected(const AbstractAspect *)
T * child(int index, ChildIndexFlags flags={}) const
AbstractAspect * parentAspect() const
Return my parent Aspect or 0 if I currently don't have one.
void beginMacro(const QString &text)
Begin an undo stack macro (series of commands)
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.
void endMacro()
End the current undo stack macro.
void setHidden(bool)
Set "hidden" property, i.e. whether to exclude this aspect from being shown in the explorer.
Base class of Aspects with MDI windows as views (AspectParts).
Definition: AbstractPart.h:36
QMenu * createContextMenu() override
Return AbstractAspect::createContextMenu() plus operations on the primary view.
QWidget * m_partView
Definition: AbstractPart.h:65
Top-level container for Curve-Point and Datasheet/Spreadsheet of datapicker.
container to open image/plot.
bool printPreview() const override
bool printView() override
QGraphicsScene * scene() const
bool exportView() const override
void axisPointsChanged(const DatapickerImage::ReferencePoints &)
QMenu * createContextMenu() override
void initErrorBar(DatapickerCurve::Errors)
QGraphicsItem * graphicsItem() const
View class for Datapicker.
int currentIndex() const
Top-level container for DatapickerCurve and DatapickerImage.
Definition: Datapicker.h:45
void handleChildAspectAboutToBeRemoved(const AbstractAspect *)
Definition: Datapicker.cpp:309
void addNewPoint(QPointF, AbstractAspect *)
Definition: Datapicker.cpp:231
bool printView() override
Definition: Datapicker.cpp:107
DatapickerView * m_view
Definition: Datapicker.h:78
~Datapicker() override
Definition: Datapicker.cpp:57
QVector3D mapSceneToLogical(QPointF) const
Definition: Datapicker.cpp:257
DatapickerCurve * m_activeCurve
Definition: Datapicker.h:79
QVector3D mapSceneLengthToLogical(QPointF) const
Definition: Datapicker.cpp:261
Transform * m_transform
Definition: Datapicker.h:80
void save(QXmlStreamWriter *) const override
Save as XML.
Definition: Datapicker.cpp:334
Spreadsheet * currentSpreadsheet() const
Definition: Datapicker.cpp:131
DatapickerImage * m_image
Definition: Datapicker.h:81
void childSelected(const AbstractAspect *) override
Definition: Datapicker.cpp:152
void datapickerItemSelected(int)
void handleChildAspectAdded(const AbstractAspect *)
Definition: Datapicker.cpp:319
bool load(XmlStreamReader *, bool preview) override
Load from XML.
Definition: Datapicker.cpp:347
bool printPreview() const override
Definition: Datapicker.cpp:117
void setChildSelectedInView(int index, bool selected)
Definition: Datapicker.cpp:184
void setSelectedInView(const bool)
Definition: Datapicker.cpp:224
void childDeselected(const AbstractAspect *) override
Definition: Datapicker.cpp:174
void handleAspectAdded(const AbstractAspect *)
Definition: Datapicker.cpp:283
Datapicker(const QString &name, const bool loading=false)
Definition: Datapicker.cpp:47
DatapickerImage * image() const
Definition: Datapicker.cpp:143
void requestUpdateActions()
DatapickerCurve * activeCurve()
Definition: Datapicker.cpp:127
QWidget * view() const override
Construct a primary view on me.
Definition: Datapicker.cpp:88
void init()
Definition: Datapicker.cpp:61
void handleAspectAboutToBeRemoved(const AbstractAspect *)
Definition: Datapicker.cpp:265
QIcon icon() const override
Definition: Datapicker.cpp:74
QMenu * createContextMenu() override
Definition: Datapicker.cpp:81
bool exportView() const override
Definition: Datapicker.cpp:97
Aspect providing a spreadsheet table with column logic.
Definition: Spreadsheet.h:40
bool exportView() const override
bool printPreview() const override
bool printView() override
QVector3D mapSceneToLogical(QPointF, const DatapickerImage::ReferencePoints &)
Definition: Transform.cpp:95
QVector3D mapSceneLengthToLogical(QPointF, const DatapickerImage::ReferencePoints &)
Definition: Transform.cpp:132
XML stream parser that supports errors as well as warnings. This class also adds line and column numb...
void raiseWarning(const QString &)
#define i18n(m)
Definition: nsl_common.h:38