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)  

XYAnalysisCurve.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  File : XYAnalysisCurve.h
3  Project : LabPlot
4  Description : Base class for all analysis curves
5  --------------------------------------------------------------------
6  Copyright : (C) 2017-2018 Alexander Semke (alexander.semke@web.de)
7  Copyright : (C) 2018 Stefan Gerlach (stefan.gerlach@uni.kn)
8 
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 /*!
31  \class XYAnalysisCurve
32  \brief Base class for all analysis curves
33 
34  \ingroup worksheet
35 */
36 
37 #include "XYAnalysisCurve.h"
38 #include "XYAnalysisCurvePrivate.h"
41 #include "backend/lib/macros.h"
42 
43 #include <KLocalizedString>
44 #include <QDateTime>
45 
47  : XYCurve(name, new XYAnalysisCurvePrivate(this), type) {
48 
49  init();
50 }
51 
53  : XYCurve(name, dd, type) {
54 
55  init();
56 }
57 
58 //no need to delete the d-pointer here - it inherits from QGraphicsItem
59 //and is deleted during the cleanup in QGraphicsScene
61 
63  Q_D(XYAnalysisCurve);
64  d->lineType = XYCurve::LineType::Line;
65  d->symbolsStyle = Symbol::Style::NoSymbols;
66 }
67 
69  const AbstractColumn* xDataColumn, const AbstractColumn* yDataColumn,
70  double xMin, double xMax) {
71 
72  int rowCount = qMin(xDataColumn->rowCount(), yDataColumn->rowCount());
73  for (int row = 0; row < rowCount; ++row) {
74  if (!xDataColumn->isValid(row) || xDataColumn->isMasked(row) ||
75  !yDataColumn->isValid(row) || yDataColumn->isMasked(row))
76  continue;
77 
78  double x = NAN;
79  switch (xDataColumn->columnMode()) {
81  x = xDataColumn->valueAt(row);
82  break;
84  x = xDataColumn->integerAt(row);
85  break;
87  x = xDataColumn->bigIntAt(row);
88  break;
89  case AbstractColumn::ColumnMode::Text: // invalid
90  break;
94  x = xDataColumn->dateTimeAt(row).toMSecsSinceEpoch();
95  }
96 
97  double y = NAN;
98  switch (yDataColumn->columnMode()) {
100  y = yDataColumn->valueAt(row);
101  break;
103  y = yDataColumn->integerAt(row);
104  break;
106  y = yDataColumn->bigIntAt(row);
107  break;
108  case AbstractColumn::ColumnMode::Text: // invalid
109  break;
113  y = yDataColumn->dateTimeAt(row).toMSecsSinceEpoch();
114  }
115 
116  // only when inside given range
117  if (x >= xMin && x <= xMax) {
118  xData.append(x);
119  yData.append(y);
120  }
121  }
122 }
123 
124 //##############################################################################
125 //########################## getter methods ##################################
126 //##############################################################################
128 BASIC_SHARED_D_READER_IMPL(XYAnalysisCurve, const XYCurve*, dataSourceCurve, dataSourceCurve)
129 const QString& XYAnalysisCurve::dataSourceCurvePath() const {
130  return d_ptr->dataSourceCurvePath;
131 }
132 
133 BASIC_SHARED_D_READER_IMPL(XYAnalysisCurve, const AbstractColumn*, xDataColumn, xDataColumn)
134 BASIC_SHARED_D_READER_IMPL(XYAnalysisCurve, const AbstractColumn*, yDataColumn, yDataColumn)
135 BASIC_SHARED_D_READER_IMPL(XYAnalysisCurve, const AbstractColumn*, y2DataColumn, y2DataColumn)
136 CLASS_SHARED_D_READER_IMPL(XYAnalysisCurve, QString, xDataColumnPath, xDataColumnPath)
137 CLASS_SHARED_D_READER_IMPL(XYAnalysisCurve, QString, yDataColumnPath, yDataColumnPath)
138 CLASS_SHARED_D_READER_IMPL(XYAnalysisCurve, QString, y2DataColumnPath, y2DataColumnPath)
139 
140 //##############################################################################
141 //################# setter methods and undo commands ##########################
142 //##############################################################################
143 STD_SETTER_CMD_IMPL_S(XYAnalysisCurve, SetDataSourceType, XYAnalysisCurve::DataSourceType, dataSourceType)
144 void XYAnalysisCurve::setDataSourceType(DataSourceType type) {
145  Q_D(XYAnalysisCurve);
146  if (type != d->dataSourceType)
147  exec(new XYAnalysisCurveSetDataSourceTypeCmd(d, type, ki18n("%1: data source type changed")));
148 }
149 
150 STD_SETTER_CMD_IMPL_F_S(XYAnalysisCurve, SetDataSourceCurve, const XYCurve*, dataSourceCurve, retransform)
151 void XYAnalysisCurve::setDataSourceCurve(const XYCurve* curve) {
152  Q_D(XYAnalysisCurve);
153  if (curve != d->dataSourceCurve) {
154  exec(new XYAnalysisCurveSetDataSourceCurveCmd(d, curve, ki18n("%1: data source curve changed")));
156 
157  //handle the changes when different columns were provided for the source curve
158  connect(curve, SIGNAL(xColumnChanged(const AbstractColumn*)), this, SLOT(handleSourceDataChanged()));
159  connect(curve, SIGNAL(yColumnChanged(const AbstractColumn*)), this, SLOT(handleSourceDataChanged()));
160  //TODO? connect(curve, SIGNAL(y2ColumnChanged(const AbstractColumn*)), this, SLOT(handleSourceDataChanged()));
161 
162  //handle the changes when the data inside of the source curve columns
165 
166  //TODO: add disconnect in the undo-function
167  }
168 }
169 
170 STD_SETTER_CMD_IMPL_S(XYAnalysisCurve, SetXDataColumn, const AbstractColumn*, xDataColumn)
171 void XYAnalysisCurve::setXDataColumn(const AbstractColumn* column) {
172  DEBUG("XYAnalysisCurve::setXDataColumn()");
173  Q_D(XYAnalysisCurve);
174  if (column != d->xDataColumn) {
175  exec(new XYAnalysisCurveSetXDataColumnCmd(d, column, ki18n("%1: assign x-data")));
177  if (column) {
178  setXDataColumnPath(column->path());
181  connect(column, SIGNAL(dataChanged(const AbstractColumn*)), this, SLOT(handleSourceDataChanged()));
183  //TODO disconnect on undo
184  } else
185  setXDataColumnPath("");
186  }
187 }
188 
189 STD_SETTER_CMD_IMPL_S(XYAnalysisCurve, SetYDataColumn, const AbstractColumn*, yDataColumn)
190 void XYAnalysisCurve::setYDataColumn(const AbstractColumn* column) {
191  DEBUG("XYAnalysisCurve::setYDataColumn()");
192  Q_D(XYAnalysisCurve);
193  if (column != d->yDataColumn) {
194  exec(new XYAnalysisCurveSetYDataColumnCmd(d, column, ki18n("%1: assign y-data")));
196  if (column) {
197  setYDataColumnPath(column->path());
200  connect(column, SIGNAL(dataChanged(const AbstractColumn*)), this, SLOT(handleSourceDataChanged()));
202  //TODO disconnect on undo
203  } else
204  setXDataColumnPath("");
205  }
206 }
207 
208 STD_SETTER_CMD_IMPL_S(XYAnalysisCurve, SetY2DataColumn, const AbstractColumn*, y2DataColumn)
209 void XYAnalysisCurve::setY2DataColumn(const AbstractColumn* column) {
210  DEBUG("XYAnalysisCurve::setY2DataColumn()");
211  Q_D(XYAnalysisCurve);
212  if (column != d->y2DataColumn) {
213  exec(new XYAnalysisCurveSetY2DataColumnCmd(d, column, ki18n("%1: assign second y-data")));
215  if (column) {
216  setY2DataColumnPath(column->path());
219  connect(column, SIGNAL(dataChanged(const AbstractColumn*)), this, SLOT(handleSourceDataChanged()));
221  //TODO disconnect on undo
222  } else
223  setXDataColumnPath("");
224  }
225 }
226 
227 void XYAnalysisCurve::setXDataColumnPath(const QString& path) {
228  Q_D(XYAnalysisCurve);
229  d->xDataColumnPath = path;
230 }
231 
232 void XYAnalysisCurve::setYDataColumnPath(const QString& path) {
233  Q_D(XYAnalysisCurve);
234  d->yDataColumnPath = path;
235 }
236 
237 void XYAnalysisCurve::setY2DataColumnPath(const QString& path) {
238  Q_D(XYAnalysisCurve);
239  d->y2DataColumnPath = path;
240 }
241 
242 //##############################################################################
243 //################################# SLOTS ####################################
244 //##############################################################################
246  Q_D(XYAnalysisCurve);
247  d->sourceDataChangedSinceLastRecalc = true;
248  emit sourceDataChanged();
249 }
250 
252  Q_D(XYAnalysisCurve);
253  if (aspect == d->xDataColumn) {
254  d->xDataColumn = nullptr;
255  d->retransform();
256  }
257 }
258 
260  Q_D(XYAnalysisCurve);
261  if (aspect == d->yDataColumn) {
262  d->yDataColumn = nullptr;
263  d->retransform();
264  }
265 }
266 
268  Q_D(XYAnalysisCurve);
269  if (aspect == d->y2DataColumn) {
270  d->y2DataColumn = nullptr;
271  d->retransform();
272  }
273 }
274 
276  Q_D(XYAnalysisCurve);
277  setXDataColumnPath(d->xDataColumn->path());
278 }
279 
281  Q_D(XYAnalysisCurve);
282  setYDataColumnPath(d->yDataColumn->path());
283 }
284 
286  Q_D(XYAnalysisCurve);
287  setYDataColumnPath(d->y2DataColumn->path());
288 }
289 
290 //##############################################################################
291 //######################### Private implementation #############################
292 //##############################################################################
294 }
295 
296 //no need to delete xColumn and yColumn, they are deleted
297 //when the parent aspect is removed
299 
300 //##############################################################################
301 //################## Serialization/Deserialization ###########################
302 //##############################################################################
303 //! Save as XML
304 void XYAnalysisCurve::save(QXmlStreamWriter* writer) const {
305  Q_D(const XYAnalysisCurve);
306 
307  writer->writeStartElement("xyAnalysisCurve");
308 
309  //write xy-curve information
310  XYCurve::save(writer);
311 
312  //write data source specific information
313  writer->writeStartElement("dataSource");
314  writer->writeAttribute("type", QString::number(static_cast<int>(d->dataSourceType)));
315  WRITE_PATH(d->dataSourceCurve, dataSourceCurve);
316  WRITE_COLUMN(d->xDataColumn, xDataColumn);
317  WRITE_COLUMN(d->yDataColumn, yDataColumn);
318  WRITE_COLUMN(d->y2DataColumn, y2DataColumn);
319  writer->writeEndElement();
320 
321  writer->writeEndElement(); //"xyAnalysisCurve"
322 }
323 
324 //! Load from XML
325 bool XYAnalysisCurve::load(XmlStreamReader* reader, bool preview) {
326  Q_D(XYAnalysisCurve);
327 
328  KLocalizedString attributeWarning = ki18n("Attribute '%1' missing or empty, default value is used");
329  QXmlStreamAttributes attribs;
330  QString str;
331 
332  while (!reader->atEnd()) {
333  reader->readNext();
334  if (reader->isEndElement() && reader->name() == "xyAnalysisCurve")
335  break;
336 
337  if (!reader->isStartElement())
338  continue;
339 
340  if (reader->name() == "xyCurve") {
341  if ( !XYCurve::load(reader, preview) )
342  return false;
343  } else if (reader->name() == "dataSource") {
344  attribs = reader->attributes();
345  READ_INT_VALUE("type", dataSourceType, XYAnalysisCurve::DataSourceType);
346  READ_PATH(dataSourceCurve);
347  READ_COLUMN(xDataColumn);
348  READ_COLUMN(yDataColumn);
349  READ_COLUMN(y2DataColumn);
350  }
351  }
352 
353  return true;
354 }
AspectType
Base class of all persistent objects in a Project.
AspectType type() const
void aspectDescriptionChanged(const AbstractAspect *)
Emitted after the name, comment or caption spec have changed.
void aspectAboutToBeRemoved(const AbstractAspect *)
Emitted before an aspect is removed from its parent.
AbstractAspect * parentAspect() const
Return my parent Aspect or 0 if I currently don't have one.
virtual QString path() const
Return the path that leads from the top-most Aspect (usually a Project) to me.
void exec(QUndoCommand *)
Execute the given command, pushing it on the undoStack() if available.
AbstractAspectPrivate * d
Interface definition for data with column logic.
virtual double valueAt(int row) const
Return the double value in row 'row'.
bool isMasked(int row) const
Return whether a certain row is masked.
virtual int rowCount() const =0
Return the data vector size.
virtual QDateTime dateTimeAt(int row) const
Return the QDateTime in row 'row'.
virtual qint64 bigIntAt(int row) const
Return the bigint value in row 'row'.
bool isValid(int row) const
Convenience method for mode-independent testing of validity.
virtual int integerAt(int row) const
Return the integer value in row 'row'.
virtual ColumnMode columnMode() const =0
Return the column mode.
XYAnalysisCurvePrivate(XYAnalysisCurve *)
~XYAnalysisCurvePrivate() override
Base class for all analysis curves.
static void copyData(QVector< double > &xData, QVector< double > &yData, const AbstractColumn *xDataColumn, const AbstractColumn *yDataColumn, double xMin, double xMax)
void xDataColumnAboutToBeRemoved(const AbstractAspect *)
void y2DataColumnAboutToBeRemoved(const AbstractAspect *)
~XYAnalysisCurve() override
void save(QXmlStreamWriter *) const override
Save as XML.
void yDataColumnAboutToBeRemoved(const AbstractAspect *)
XYAnalysisCurve(const QString &, AspectType type)
const QString & dataSourceCurvePath() const
void y2DataColumnNameChanged()
bool load(XmlStreamReader *, bool preview) override
Load from XML.
void handleSourceDataChanged()
void sourceDataChanged()
A 2D-curve, provides an interface for editing many properties of the curve.
Definition: XYCurve.h:46
void yDataChanged()
void dataChanged()
void xDataChanged()
bool load(XmlStreamReader *, bool preview) override
Load from XML.
Definition: XYCurve.cpp:3048
void xColumnChanged(const AbstractColumn *)
void save(QXmlStreamWriter *) const override
Save as XML.
Definition: XYCurve.cpp:2955
void yColumnChanged(const AbstractColumn *)
double y(double x, bool &valueFound) const
Definition: XYCurve.cpp:2132
XML stream parser that supports errors as well as warnings. This class also adds line and column numb...
#define CLASS_SHARED_D_READER_IMPL(classname, type, method, var)
Definition: macros.h:154
#define DEBUG(x)
Definition: macros.h:50
#define STD_SETTER_CMD_IMPL_S(class_name, cmd_name, value_type, field_name)
Definition: macros.h:207
#define WRITE_PATH(obj, name)
Definition: macros.h:505
#define STD_SETTER_CMD_IMPL_F_S(class_name, cmd_name, value_type, field_name, finalize_method)
Definition: macros.h:215
#define READ_COLUMN(columnName)
Definition: macros.h:462
#define READ_INT_VALUE(name, var, type)
Definition: macros.h:468
#define BASIC_SHARED_D_READER_IMPL(classname, type, method, var)
Definition: macros.h:127
#define READ_PATH(name)
Definition: macros.h:514
#define WRITE_COLUMN(column, columnName)
Definition: macros.h:451