Commit c9768629 authored by Knut Franke's avatar Knut Franke

- Removed explicit handling of invalid cells in favour of NaN, QString() (null

  string) and QDateTime() (invalid date/time). The advantage is a reduction in
  complexity (fewer methods) as well as that if some calculations yields an
  undefined/invalid result, you can simply return the approriate invalid value
  instead of having to make sure that isInvalid() returns true for these cells.
parent 2bb9764b
......@@ -99,7 +99,6 @@ void AbstractColumn::setColumnMode(SciDAVis::ColumnMode) {}
*
* This function will return false if the data type
* of 'other' is not the same as the type of 'this'.
* The validity information for the rows is also copied.
* Use a filter to convert a column to another type.
*/
bool AbstractColumn::copy(const AbstractColumn *other) {
......@@ -112,7 +111,6 @@ bool AbstractColumn::copy(const AbstractColumn *other) {
*
* This function will return false if the data type
* of 'other' is not the same as the type of 'this'.
* The validity information for the rows is also copied.
* \param source pointer to the column to copy
* \param source_start first row to copy in the column to copy
* \param destination_start first row to copy in
......@@ -132,7 +130,7 @@ bool AbstractColumn::copy(const AbstractColumn *source, int source_start, int de
*/
/**
* \brief Insert some empty (or initialized with zero) rows
* \brief Insert some empty (or initialized with invalid values) rows
*/
void AbstractColumn::insertRows(int before, int count) {
Q_UNUSED(before) Q_UNUSED(count)
......@@ -162,31 +160,26 @@ void AbstractColumn::setPlotDesignation(SciDAVis::PlotDesignation pd) {
*/
void AbstractColumn::clear() {}
////////////////////////////////////////////////////////////////////////////////////////////////////
//! \name IntervalAttribute related functions
//@{
////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* \brief Return whether a certain row contains an invalid value
*/
bool AbstractColumn::isInvalid(int row) const {
return !Interval<int>(0, rowCount()-1).contains(row);
}
/**
* \brief Return whether a certain interval of rows contains only invalid values
* \brief Convenience method for mode-inpedpendent testing of validity
*/
bool AbstractColumn::isInvalid(Interval<int> i) const {
return !Interval<int>(0, rowCount()-1).contains(i);
bool AbstractColumn::isValid(int row) const {
switch (columnMode()) {
case SciDAVis::Numeric:
return !isnan(valueAt(row));
case SciDAVis::Text:
return !textAt(row).isNull();
case SciDAVis::DateTime:
case SciDAVis::Month:
case SciDAVis::Day:
return dateTimeAt(row).isValid();
}
}
/**
* \brief Return all intervals of invalid rows
*/
QList< Interval<int> > AbstractColumn::invalidIntervals() const {
return QList< Interval<int> >();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//! \name IntervalAttribute related functions
//@{
////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* \brief Return whether a certain row is masked
......@@ -211,34 +204,11 @@ QList< Interval<int> > AbstractColumn::maskedIntervals() const {
return QList< Interval<int> >();
}
/**
* \brief Clear all validity information
*/
void AbstractColumn::clearValidity() {};
/**
* \brief Clear all masking information
*/
void AbstractColumn::clearMasks() {};
/**
* \brief Set an interval invalid or valid
*
* \param i the interval
* \param invalid true: set invalid, false: set valid
*/
void AbstractColumn::setInvalid(Interval<int> i, bool invalid) {
Q_UNUSED(i)
Q_UNUSED(invalid)
};
/**
* \brief Overloaded function for convenience
*/
void AbstractColumn::setInvalid(int row, bool invalid) {
Q_UNUSED(row) Q_UNUSED(invalid)
}
/**
* \brief Set an interval masked
*
......@@ -482,7 +452,7 @@ void AbstractColumn::replaceValues(int first, const QVector<double>& new_values)
/**
* \fn void AbstractColumn::dataAboutToChange(const AbstractColumn *source)
* \brief Data (including validity) of the column will be changed
* \brief Data of the column will be changed
*
* 'source' is always the this pointer of the column that
* emitted this signal. This way it's easier to use
......@@ -491,7 +461,7 @@ void AbstractColumn::replaceValues(int first, const QVector<double>& new_values)
/**
* \fn void AbstractColumn::dataChanged(const AbstractColumn *source)
* \brief Data (including validity) of the column has changed
* \brief Data of the column has changed
*
* Important: When data has changed also the number
* of rows in the column may have changed without
......
......@@ -63,16 +63,11 @@ class AbstractColumn : public AbstractAspect
virtual void setPlotDesignation(SciDAVis::PlotDesignation pd);
virtual void clear();
virtual bool isInvalid(int row) const;
virtual bool isInvalid(Interval<int> i) const;
virtual QList< Interval<int> > invalidIntervals() const;
bool isValid(int row) const;
virtual bool isMasked(int row) const;
virtual bool isMasked(Interval<int> i) const;
virtual QList< Interval<int> > maskedIntervals() const;
virtual void clearValidity();
virtual void clearMasks();
virtual void setInvalid(Interval<int> i, bool invalid = true);
virtual void setInvalid(int row, bool invalid = true);
virtual void setMasked(Interval<int> i, bool mask = true);
virtual void setMasked(int row, bool mask = true);
......
......@@ -296,27 +296,6 @@ void AbstractSimpleFilter::setMasked(int row, bool mask) {
//@}
////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* \brief Return whether a certain row contains an invalid value
*/
bool AbstractSimpleFilter::isInvalid(int row) const {
return m_inputs.value(0) ? m_inputs.at(0)->isInvalid(row) : false;
}
/**
* \brief Return whether a certain interval of rows contains only invalid values
*/
bool AbstractSimpleFilter::isInvalid(Interval<int> i) const {
return m_inputs.value(0) ? m_inputs.at(0)->isInvalid(i) : false;
}
/**
* \brief Return all intervals of invalid rows
*/
QList< Interval<int> > AbstractSimpleFilter::invalidIntervals() const {
return m_inputs.value(0) ? m_inputs.at(0)->invalidIntervals() : QList< Interval<int> >();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//!\name signal handlers
//@{
......
......@@ -65,10 +65,6 @@ class AbstractSimpleFilter : public AbstractFilter
virtual void setMasked(Interval<int> i, bool mask = true);
virtual void setMasked(int row, bool mask = true);
virtual bool isInvalid(int row) const;
virtual bool isInvalid(Interval<int> i) const;
virtual QList< Interval<int> > invalidIntervals() const;
virtual void save(QXmlStreamWriter * writer) const;
virtual bool load(XmlStreamReader * reader);
virtual void writeExtraAttributes(QXmlStreamWriter * writer) const;
......@@ -101,9 +97,6 @@ class SimpleFilterColumn : public AbstractColumn
virtual SciDAVis::ColumnMode columnMode() const;
virtual int rowCount() const { return m_owner->rowCount(); }
virtual SciDAVis::PlotDesignation plotDesignation() const { return m_owner->plotDesignation(); }
virtual bool isInvalid(int row) const { return m_owner->isInvalid(row); }
virtual bool isInvalid(Interval<int> i) const { return m_owner->isInvalid(i); }
virtual QList< Interval<int> > invalidIntervals() const { return m_owner->invalidIntervals(); }
virtual bool isMasked(int row) const { return m_owner->isMasked(row); }
virtual bool isMasked(Interval<int> i) const { return m_owner->isMasked(i); }
virtual QList< Interval<int> > maskedIntervals() const { return m_owner->maskedIntervals(); }
......
......@@ -43,7 +43,7 @@
* This class represents a column, i.e., (mathematically) a 1D vector of
* values with a header. It provides a public reading and (undo aware) writing
* interface as defined in AbstractColumn. It manages special attributes
* of column rows such as masking and a validity flag. A column
* of column rows such as masking. A column
* can have one of currently three data types: double, QString, or
* QDateTime. The string representation of the values can differ depending
* on the mode of the column.
......@@ -76,12 +76,11 @@ Column::Column(const QString& name, SciDAVis::ColumnMode mode)
*
* \param name the column name (= aspect name)
* \param data initial data vector
* \param validity a list of invalid intervals (optional)
*/
Column::Column(const QString& name, QVector<double> data, IntervalAttribute<bool> validity)
Column::Column(const QString& name, QVector<double> data)
: AbstractColumn(name)
{
m_column_private = new Private(this, SciDAVis::Numeric, new QVector<double>(data), validity);
m_column_private = new Private(this, SciDAVis::Numeric, new QVector<double>(data));
init();
}
......@@ -90,12 +89,11 @@ Column::Column(const QString& name, QVector<double> data, IntervalAttribute<bool
*
* \param name the column name (= aspect name)
* \param data initial data vector
* \param validity a list of invalid intervals (optional)
*/
Column::Column(const QString& name, QStringList data, IntervalAttribute<bool> validity)
Column::Column(const QString& name, QStringList data)
: AbstractColumn(name)
{
m_column_private = new Private(this, SciDAVis::Text, new QStringList(data), validity);
m_column_private = new Private(this, SciDAVis::Text, new QStringList(data));
init();
}
......@@ -104,12 +102,11 @@ Column::Column(const QString& name, QStringList data, IntervalAttribute<bool> va
*
* \param name the column name (= aspect name)
* \param data initial data vector
* \param validity a list of invalid intervals (optional)
*/
Column::Column(const QString& name, QList<QDateTime> data, IntervalAttribute<bool> validity)
Column::Column(const QString& name, QList<QDateTime> data)
: AbstractColumn(name)
{
m_column_private = new Private(this, SciDAVis::DateTime, new QList<QDateTime>(data), validity);
m_column_private = new Private(this, SciDAVis::DateTime, new QList<QDateTime>(data));
init();
}
......@@ -170,7 +167,6 @@ void Column::setColumnMode(SciDAVis::ColumnMode mode)
*
* This function will return false if the data type
* of 'other' is not the same as the type of 'this'.
* The validity information for the rows is also copied.
* Use a filter to convert a column to another type.
*/
bool Column::copy(const AbstractColumn * other)
......@@ -186,7 +182,6 @@ bool Column::copy(const AbstractColumn * other)
*
* This function will return false if the data type
* of 'other' is not the same as the type of 'this'.
* The validity information for the rows is also copied.
* \param other pointer to the column to copy
* \param src_start first row to copy in the column to copy
* \param dest_start first row to copy in
......@@ -252,14 +247,6 @@ void Column::clear()
exec(new ColumnClearCmd(m_column_private));
}
/**
* \brief Clear all validity information
*/
void Column::clearValidity()
{
exec(new ColumnClearValidityCmd(m_column_private));
}
/**
* \brief Clear all masking information
*/
......@@ -268,25 +255,6 @@ void Column::clearMasks()
exec(new ColumnClearMasksCmd(m_column_private));
}
/**
* \brief Set an interval invalid or valid
*
* \param i the interval
* \param invalid true: set invalid, false: set valid
*/
void Column::setInvalid(Interval<int> i, bool invalid)
{
exec(new ColumnSetInvalidCmd(m_column_private, i, invalid));
}
/**
* \brief Overloaded function for convenience
*/
void Column::setInvalid(int row, bool invalid)
{
setInvalid(Interval<int>(row,row), invalid);
}
/**
* \brief Set an interval masked
*
......@@ -547,7 +515,6 @@ void Column::save(QXmlStreamWriter * writer) const
{
writer->writeStartElement("row");
writer->writeAttribute("index", QString::number(i));
writer->writeAttribute("invalid", isInvalid(i) ? "yes" : "no");
writer->writeCharacters(QString::number(valueAt(i), 'e', 16));
writer->writeEndElement();
}
......@@ -557,7 +524,6 @@ void Column::save(QXmlStreamWriter * writer) const
{
writer->writeStartElement("row");
writer->writeAttribute("index", QString::number(i));
writer->writeAttribute("invalid", isInvalid(i) ? "yes" : "no");
writer->writeCharacters(textAt(i));
writer->writeEndElement();
}
......@@ -570,7 +536,6 @@ void Column::save(QXmlStreamWriter * writer) const
{
writer->writeStartElement("row");
writer->writeAttribute("index", QString::number(i));
writer->writeAttribute("invalid", isInvalid(i) ? "yes" : "no");
#if QT_VERSION < 0x040400 // avoid a bug in Qt < 4.4
QString str = dateTimeAt(i).toString("yyyy-dd-MM hh:mm:ss:zzz");
int should_be_length = 4;
......@@ -641,7 +606,6 @@ bool Column::load(XmlStreamReader * reader)
setComment("");
if (rowCount() > 0)
removeRows(0, rowCount());
clearValidity();
clearMasks();
clearFormulas();
// read child elements
......@@ -769,9 +733,6 @@ bool Column::XmlReadRow(XmlStreamReader * reader)
return false;
}
str = attribs.value(reader->namespaceUri().toString(), "invalid").toString();
if(str == "yes") setInvalid(index);
str = reader->readElementText();
switch(columnMode()) {
case SciDAVis::Numeric:
......@@ -859,30 +820,6 @@ ColumnStringIO *Column::asStringColumn() const {
//@{
////////////////////////////////////////////////////////////////////////////////
/**
* \brief Return whether a certain row contains an invalid value
*/
bool Column::isInvalid(int row) const
{
return m_column_private->isInvalid(row);
}
/**
* \brief Return whether a certain interval of rows contains only invalid values
*/
bool Column::isInvalid(Interval<int> i) const
{
return m_column_private->isInvalid(i);
}
/**
* \brief Return all intervals of invalid rows
*/
QList< Interval<int> > Column::invalidIntervals() const
{
return m_column_private->invalidIntervals();
}
/**
* \brief Return whether a certain row is masked
*/
......
......@@ -49,9 +49,9 @@ class Column : public AbstractColumn
static void staticInit();
Column(const QString& name, SciDAVis::ColumnMode mode);
Column(const QString& name, QVector<double> data, IntervalAttribute<bool> validity = IntervalAttribute<bool>());
Column(const QString& name, QStringList data, IntervalAttribute<bool> validity = IntervalAttribute<bool>());
Column(const QString& name, QList<QDateTime> data, IntervalAttribute<bool> validity = IntervalAttribute<bool>());
Column(const QString& name, QVector<double> data);
Column(const QString& name, QStringList data);
Column(const QString& name, QList<QDateTime> data);
void init();
~Column();
......@@ -73,16 +73,10 @@ class Column : public AbstractColumn
AbstractSimpleFilter *outputFilter() const;
ColumnStringIO *asStringColumn() const;
bool isInvalid(int row) const;
bool isInvalid(Interval<int> i) const;
QList< Interval<int> > invalidIntervals() const;
bool isMasked(int row) const;
bool isMasked(Interval<int> i) const;
QList< Interval<int> > maskedIntervals() const;
void clearValidity();
void clearMasks();
void setInvalid(Interval<int> i, bool invalid = true);
void setInvalid(int row, bool invalid = true);
void setMasked(Interval<int> i, bool mask = true);
void setMasked(int row, bool mask = true);
......@@ -140,12 +134,6 @@ class ColumnStringIO : public AbstractColumn
virtual int rowCount() const { return m_owner->rowCount(); }
virtual QString textAt(int row) const;
virtual void setTextAt(int row, const QString &value);
virtual bool isInvalid(int row) const {
if (m_setting)
return false;
else
return m_owner->isInvalid(row);
}
private:
Column * m_owner;
......
......@@ -151,13 +151,11 @@ Column::Private::Private(Column * owner, SciDAVis::ColumnMode mode)
/**
* \brief Special ctor (to be called from Column only!)
*/
Column::Private::Private(Column * owner, SciDAVis::ColumnMode mode, void * data,
IntervalAttribute<bool> validity)
Column::Private::Private(Column * owner, SciDAVis::ColumnMode mode, void * data)
: m_owner(owner)
{
m_column_mode = mode;
m_data = data;
m_validity = validity;
switch(mode)
{
......@@ -266,22 +264,22 @@ void Column::Private::setColumnMode(SciDAVis::ColumnMode mode)
break;
case SciDAVis::Text:
filter = outputFilter(); filter_is_temporary = false;
temp_col = new Column("temp_col", *(static_cast< QVector<double>* >(old_data)), m_validity);
temp_col = new Column("temp_col", *(static_cast< QVector<double>* >(old_data)));
m_data = new QStringList();
break;
case SciDAVis::DateTime:
filter = new Double2DateTimeFilter(); filter_is_temporary = true;
temp_col = new Column("temp_col", *(static_cast< QVector<double>* >(old_data)), m_validity);
temp_col = new Column("temp_col", *(static_cast< QVector<double>* >(old_data)));
m_data = new QList<QDateTime>();
break;
case SciDAVis::Month:
filter = new Double2MonthFilter(); filter_is_temporary = true;
temp_col = new Column("temp_col", *(static_cast< QVector<double>* >(old_data)), m_validity);
temp_col = new Column("temp_col", *(static_cast< QVector<double>* >(old_data)));
m_data = new QList<QDateTime>();
break;
case SciDAVis::Day:
filter = new Double2DayOfWeekFilter(); filter_is_temporary = true;
temp_col = new Column("temp_col", *(static_cast< QVector<double>* >(old_data)), m_validity);
temp_col = new Column("temp_col", *(static_cast< QVector<double>* >(old_data)));
m_data = new QList<QDateTime>();
break;
} // switch(mode)
......@@ -294,22 +292,22 @@ void Column::Private::setColumnMode(SciDAVis::ColumnMode mode)
break;
case SciDAVis::Numeric:
filter = new String2DoubleFilter(); filter_is_temporary = true;
temp_col = new Column("temp_col", *(static_cast< QStringList* >(old_data)), m_validity);
temp_col = new Column("temp_col", *(static_cast< QStringList* >(old_data)));
m_data = new QVector<double>();
break;
case SciDAVis::DateTime:
filter = new String2DateTimeFilter(); filter_is_temporary = true;
temp_col = new Column("temp_col", *(static_cast< QStringList* >(old_data)), m_validity);
temp_col = new Column("temp_col", *(static_cast< QStringList* >(old_data)));
m_data = new QList<QDateTime>();
break;
case SciDAVis::Month:
filter = new String2MonthFilter(); filter_is_temporary = true;
temp_col = new Column("temp_col", *(static_cast< QStringList* >(old_data)), m_validity);
temp_col = new Column("temp_col", *(static_cast< QStringList* >(old_data)));
m_data = new QList<QDateTime>();
break;
case SciDAVis::Day:
filter = new String2DayOfWeekFilter(); filter_is_temporary = true;
temp_col = new Column("temp_col", *(static_cast< QStringList* >(old_data)), m_validity);
temp_col = new Column("temp_col", *(static_cast< QStringList* >(old_data)));
m_data = new QList<QDateTime>();
break;
} // switch(mode)
......@@ -326,7 +324,7 @@ void Column::Private::setColumnMode(SciDAVis::ColumnMode mode)
break;
case SciDAVis::Text:
filter = outputFilter(); filter_is_temporary = false;
temp_col = new Column("temp_col", *(static_cast< QList<QDateTime>* >(old_data)), m_validity);
temp_col = new Column("temp_col", *(static_cast< QList<QDateTime>* >(old_data)));
m_data = new QStringList();
break;
case SciDAVis::Numeric:
......@@ -337,7 +335,7 @@ void Column::Private::setColumnMode(SciDAVis::ColumnMode mode)
else
filter = new DateTime2DoubleFilter();
filter_is_temporary = true;
temp_col = new Column("temp_col", *(static_cast< QList<QDateTime>* >(old_data)), m_validity);
temp_col = new Column("temp_col", *(static_cast< QList<QDateTime>* >(old_data)));
m_data = new QVector<double>();
break;
case SciDAVis::Month:
......@@ -409,10 +407,10 @@ void Column::Private::setColumnMode(SciDAVis::ColumnMode mode)
/**
* \brief Replace all mode related members
*
* Replace column mode, data type, data pointer, validity and filters directly
* Replace column mode, data type, data pointer and filters directly
*/
void Column::Private::replaceModeData(SciDAVis::ColumnMode mode, void * data,
AbstractSimpleFilter * in_filter, AbstractSimpleFilter * out_filter, IntervalAttribute<bool> validity)
AbstractSimpleFilter * in_filter, AbstractSimpleFilter * out_filter)
{
emit m_owner->modeAboutToChange(m_owner);
// disconnect formatChanged()
......@@ -458,28 +456,19 @@ void Column::Private::replaceModeData(SciDAVis::ColumnMode mode, void * data,
break;
}
m_validity = validity;
emit m_owner->modeChanged(m_owner);
}
/**
* \brief Replace data pointer and validity
* \brief Replace data pointer
*/
void Column::Private::replaceData(void * data, IntervalAttribute<bool> validity)
void Column::Private::replaceData(void * data)
{
emit m_owner->dataAboutToChange(m_owner);
m_data = data;
m_validity = validity;
emit m_owner->dataChanged(m_owner);
}
/**
* \brief Return the validity interval attribute
*/
IntervalAttribute<bool> Column::Private::validityAttribute() const {
return m_validity;
}
/**
* \brief Return the masking interval attribute
*/
......@@ -492,7 +481,6 @@ IntervalAttribute<bool> Column::Private::maskingAttribute() const {
*
* This function will return false if the data type
* of 'other' is not the same as the type of 'this'.
* The validity information for the rows is also copied.
* Use a filter to convert a column to another type.
*/
bool Column::Private::copy(const AbstractColumn * other)
......@@ -527,8 +515,6 @@ bool Column::Private::copy(const AbstractColumn * other)
break;
}
}
// copy the validity information
m_validity = other->invalidIntervals();
emit m_owner->dataChanged(m_owner);
......@@ -540,7 +526,6 @@ bool Column::Private::copy(const AbstractColumn * other)
*
* This function will return false if the data type
* of 'other' is not the same as the type of 'this'.
* The validity information for the rows is also copied.
* \param other pointer to the column to copy
* \param src_start first row to copy in the column to copy
* \param dest_start first row to copy in
......@@ -552,8 +537,6 @@ bool Column::Private::copy(const AbstractColumn * source, int source_start, int
if (num_rows == 0) return true;
emit m_owner->dataAboutToChange(m_owner);
if (dest_start+1-rowCount() > 1)
m_validity.setValue(Interval<int>(rowCount(), dest_start-1), true);
if (dest_start + num_rows > rowCount())
resizeTo(dest_start + num_rows);
......@@ -577,9 +560,6 @@ bool Column::Private::copy(const AbstractColumn * source, int source_start, int
static_cast< QList<QDateTime>* >(m_data)->replace(dest_start+i, source->dateTimeAt(source_start + i));
break;
}
// copy the validity information
for(int i=0; i<num_rows; i++)
setInvalid(dest_start+i, source->isInvalid(source_start+i));
emit m_owner->dataChanged(m_owner);
......@@ -591,7 +571,6 @@ bool Column::Private::copy(const AbstractColumn * source, int source_start, int
*
* This function will return false if the data type
* of 'other' is not the same as the type of 'this'.
* The validity information for the rows is also copied.
* Use a filter to convert a column to another type.
*/
bool Column::Private::copy(const Private * other)
......@@ -626,8 +605,6 @@ bool Column::Private::copy(const Private * other)
break;
}
}
// copy the validity information
m_validity = other->invalidIntervals();
emit m_owner->dataChanged(m_owner);
......@@ -639,7 +616,6 @@ bool Column::Private::copy(const Private * other)
*
* This function will return false if the data type
* of 'other' is not the same as the type of 'this'.