Logo Search packages:      
Sourcecode: scidavis version File versions  Download package

Column.cpp

/***************************************************************************
    File                 : Column.cpp
    Project              : SciDAVis
    Description          : Aspect that manages a column
    --------------------------------------------------------------------
    Copyright            : (C) 2007-2009 Tilman Benkert (thzs*gmx.net)
                           (replace * with @ in the email addresses) 

 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *  This program is free software; you can redistribute it and/or modify   *
 *  it under the terms of the GNU General Public License as published by   *
 *  the Free Software Foundation; either version 2 of the License, or      *
 *  (at your option) any later version.                                    *
 *                                                                         *
 *  This program is distributed in the hope that it will be useful,        *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
 *  GNU General Public License for more details.                           *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the Free Software           *
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
 *   Boston, MA  02110-1301  USA                                           *
 *                                                                         *
 ***************************************************************************/

#include "core/column/Column.h"
#include "core/column/ColumnPrivate.h"
#include "core/column/columncommands.h"
#include "lib/XmlStreamReader.h"
#include <QIcon>
#include <QXmlStreamWriter>
#include <QtDebug>

00038 Column::Column(const QString& name, SciDAVis::ColumnMode mode)
 : AbstractColumn(name)
{
      d_column_private = new Private(this, mode);
      d_string_io = new ColumnStringIO(this);
      d_column_private->inputFilter()->input(0,d_string_io);
      outputFilter()->input(0,this);
      addChild(d_column_private->inputFilter());
      addChild(outputFilter());
}

00049 Column::Column(const QString& name, QVector<double> data, IntervalAttribute<bool> validity)
 : AbstractColumn(name)
{
      d_column_private = new Private(this, SciDAVis::TypeDouble, 
            SciDAVis::Numeric, new QVector<double>(data), validity);
      d_string_io = new ColumnStringIO(this);
      d_column_private->inputFilter()->input(0,d_string_io);
      outputFilter()->input(0,this);
      addChild(d_column_private->inputFilter());
      addChild(outputFilter());
}

00061 Column::Column(const QString& name, QStringList data, IntervalAttribute<bool> validity)
 : AbstractColumn(name)
{
      d_column_private = new Private(this, SciDAVis::TypeQString,
            SciDAVis::Text, new QStringList(data), validity);
      d_string_io = new ColumnStringIO(this);
      d_column_private->inputFilter()->input(0,d_string_io);
      outputFilter()->input(0,this);
      addChild(d_column_private->inputFilter());
      addChild(outputFilter());
}

00073 Column::Column(const QString& name, QList<QDateTime> data, IntervalAttribute<bool> validity)
 : AbstractColumn(name)
{
      d_column_private = new Private(this, SciDAVis::TypeQDateTime, 
            SciDAVis::DateTime, new QList<QDateTime>(data), validity);
      d_string_io = new ColumnStringIO(this);
      d_column_private->inputFilter()->input(0,d_string_io);
      outputFilter()->input(0,this);
      addChild(d_column_private->inputFilter());
      addChild(outputFilter());
}

00085 Column::~Column()
{
      delete d_column_private;
}

00090 void Column::setColumnMode(SciDAVis::ColumnMode mode)
{
      if(mode == columnMode()) return;
      beginMacro(QObject::tr("%1: change column type").arg(name()));
      AbstractSimpleFilter * old_input_filter = d_column_private->inputFilter();
      AbstractSimpleFilter * old_output_filter = outputFilter();
      exec(new ColumnSetModeCmd(d_column_private, mode));
      if (d_column_private->inputFilter() != old_input_filter) 
      {
            removeChild(old_input_filter);
            addChild(d_column_private->inputFilter());
            d_column_private->inputFilter()->input(0,d_string_io);
      }
      if (outputFilter() != old_output_filter) 
      {
            removeChild(old_output_filter);
            addChild(outputFilter());
            outputFilter()->input(0, this);
      }
      endMacro();
}


00113 bool Column::copy(const AbstractColumn * other)
{
      Q_CHECK_PTR(other);
      if(other->dataType() != dataType()) return false;
      exec(new ColumnFullCopyCmd(d_column_private, other));
      return true;
}

00121 bool Column::copy(const AbstractColumn * source, int source_start, int dest_start, int num_rows)
{
      Q_CHECK_PTR(source);
      if(source->dataType() != dataType()) return false;
      exec(new ColumnPartialCopyCmd(d_column_private, source, source_start, dest_start, num_rows));
      return true;
}

00129 void Column::insertRows(int before, int count)
{
      if(count > 0)
            exec(new ColumnInsertEmptyRowsCmd(d_column_private, before, count));
}

00135 void Column::removeRows(int first, int count)
{
      if(count > 0)
            exec(new ColumnRemoveRowsCmd(d_column_private, first, count));
}

00141 void Column::setPlotDesignation(SciDAVis::PlotDesignation pd)
{
      if(pd != plotDesignation())
            exec(new ColumnSetPlotDesignationCmd(d_column_private, pd));
}

00147 void Column::clear()
{
      exec(new ColumnClearCmd(d_column_private));
}

00152 void Column::notifyReplacement(const AbstractColumn* replacement)
{
      emit aboutToBeReplaced(this, replacement); 
}

00157 void Column::clearValidity()
{
      exec(new ColumnClearValidityCmd(d_column_private));
}

00162 void Column::clearMasks()
{
      exec(new ColumnClearMasksCmd(d_column_private));
}

00167 void Column::setInvalid(Interval<int> i, bool invalid)
{
      exec(new ColumnSetInvalidCmd(d_column_private, i, invalid));
}

00172 void Column::setInvalid(int row, bool invalid)
{
      setInvalid(Interval<int>(row,row), invalid);
}

00177 void Column::setMasked(Interval<int> i, bool mask)
{
      exec(new ColumnSetMaskedCmd(d_column_private, i, mask));
}

00182 void Column::setMasked(int row, bool mask)
{
      setMasked(Interval<int>(row,row), mask);
}

00187 void Column::setFormula(Interval<int> i, QString formula)
{
      exec(new ColumnSetFormulaCmd(d_column_private, i, formula));
}

00192 void Column::setFormula(int row, QString formula)
{
      setFormula(Interval<int>(row, row), formula);
}

00197 void Column::clearFormulas()
{
      exec(new ColumnClearFormulasCmd(d_column_private));
}

00202 void Column::setTextAt(int row, const QString& new_value)
{
      exec(new ColumnSetTextCmd(d_column_private, row, new_value));
}

00207 void Column::replaceTexts(int first, const QStringList& new_values)
{
      if (!new_values.isEmpty())
            exec(new ColumnReplaceTextsCmd(d_column_private, first, new_values));
}

00213 void Column::setDateAt(int row, const QDate& new_value)
{
      setDateTimeAt(row, QDateTime(new_value, timeAt(row)));
}

00218 void Column::setTimeAt(int row,const QTime& new_value)
{
      setDateTimeAt(row, QDateTime(dateAt(row), new_value));
}

00223 void Column::setDateTimeAt(int row, const QDateTime& new_value)
{
      exec(new ColumnSetDateTimeCmd(d_column_private, row, new_value));
}

00228 void Column::replaceDateTimes(int first, const QList<QDateTime>& new_values)
{
      if (!new_values.isEmpty())
            exec(new ColumnReplaceDateTimesCmd(d_column_private, first, new_values));
}

00234 void Column::setValueAt(int row, double new_value)
{
      exec(new ColumnSetValueCmd(d_column_private, row, new_value));
}

00239 void Column::replaceValues(int first, const QVector<double>& new_values)
{
      if (!new_values.isEmpty())
            exec(new ColumnReplaceValuesCmd(d_column_private, first, new_values));
}

00245 QString Column::textAt(int row) const
{
      return d_column_private->textAt(row);
}

00250 QDate Column::dateAt(int row) const
{
      return d_column_private->dateAt(row);
}

00255 QTime Column::timeAt(int row) const
{
      return d_column_private->timeAt(row);
}

00260 QDateTime Column::dateTimeAt(int row) const
{
      return d_column_private->dateTimeAt(row);
}

00265 double Column::valueAt(int row) const
{
      return d_column_private->valueAt(row);
}

00270 QIcon Column::icon() const
{
      switch(dataType())
      {
            case SciDAVis::TypeDouble:
                  return QIcon(QPixmap(":/numerictype.png"));
            case SciDAVis::TypeQString:
                  return QIcon(QPixmap(":/texttype.png"));
            case SciDAVis::TypeQDateTime:
                  return QIcon(QPixmap(":/datetype.png"));
      }
      return QIcon();
}

00284 void Column::save(QXmlStreamWriter * writer) const
{
      writer->writeStartElement("column");
      writeBasicAttributes(writer);
      writer->writeAttribute("type", SciDAVis::enumValueToString(dataType(), "ColumnDataType"));
      writer->writeAttribute("mode", SciDAVis::enumValueToString(columnMode(), "ColumnMode"));
      writer->writeAttribute("plot_designation", SciDAVis::enumValueToString(plotDesignation(), "PlotDesignation"));
      writeCommentElement(writer);
      writer->writeStartElement("input_filter");
      d_column_private->inputFilter()->save(writer);
      writer->writeEndElement();
      writer->writeStartElement("output_filter");
      outputFilter()->save(writer);
      writer->writeEndElement();
      QList< Interval<int> > masks = maskedIntervals();
      foreach(Interval<int> interval, masks)
      {
            writer->writeStartElement("mask");
            writer->writeAttribute("start_row", QString::number(interval.start()));
            writer->writeAttribute("end_row", QString::number(interval.end()));
            writer->writeEndElement();
      }
      QList< Interval<int> > formulas = formulaIntervals();
      foreach(Interval<int> interval, formulas)
      {
            writer->writeStartElement("formula");
            writer->writeAttribute("start_row", QString::number(interval.start()));
            writer->writeAttribute("end_row", QString::number(interval.end()));
            writer->writeCharacters(formula(interval.start()));
            writer->writeEndElement();
      }
      int i;
      switch(dataType())
      {
            case SciDAVis::TypeDouble:
                  for(i=0; i<rowCount(); i++)
                  {
                        writer->writeStartElement("row");
                        writer->writeAttribute("type", SciDAVis::enumValueToString(dataType(), "ColumnDataType"));
                        writer->writeAttribute("index", QString::number(i));
                        writer->writeAttribute("invalid", isInvalid(i) ? "yes" : "no");
                        writer->writeCharacters(QString::number(valueAt(i), 'e', 16));
                        writer->writeEndElement();
                  }
                  break;
            case SciDAVis::TypeQString:
                  for(i=0; i<rowCount(); i++)
                  {
                        writer->writeStartElement("row");
                        writer->writeAttribute("type", SciDAVis::enumValueToString(dataType(), "ColumnDataType"));
                        writer->writeAttribute("index", QString::number(i));
                        writer->writeAttribute("invalid", isInvalid(i) ? "yes" : "no");
                        writer->writeCharacters(textAt(i));
                        writer->writeEndElement();
                  }
                  break;

            case SciDAVis::TypeQDateTime:
                  for(i=0; i<rowCount(); i++)
                  {
                        writer->writeStartElement("row");
                        writer->writeAttribute("type", SciDAVis::enumValueToString(dataType(), "ColumnDataType"));
                        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;
                        int actual_length = dateTimeAt(i).toString("yyyy").length();
                        while (actual_length < should_be_length)
                        {
                              str.prepend("0");
                              actual_length++;
                        }
                        writer->writeCharacters(str);
#else
                        writer->writeCharacters(dateTimeAt(i).toString("yyyy-dd-MM hh:mm:ss:zzz"));
#endif
                        writer->writeEndElement();
                  }
                  break;
      }
      writer->writeEndElement(); // "column"
}


00369 bool Column::load(XmlStreamReader * reader)
{
      if(reader->isStartElement() && reader->name() == "column") 
      {
            if (!readBasicAttributes(reader)) return false;

            QXmlStreamAttributes attribs = reader->attributes();
            QString str;

            // read type
            str = attribs.value(reader->namespaceUri().toString(), "type").toString();
            if(str.isEmpty())
            {
                  reader->raiseError(tr("column type missing"));
                  return false;
            }
            int type_code = SciDAVis::enumStringToValue(str, "ColumnDataType");
            if(type_code == -1)
            {
                  reader->raiseError(tr("column type invalid"));
                  return false;
            }
            // read mode
            str = attribs.value(reader->namespaceUri().toString(), "mode").toString();
            if(str.isEmpty())
            {
                  reader->raiseError(tr("column mode missing"));
                  return false;
            }
            int mode_code = SciDAVis::enumStringToValue(str, "ColumnMode");
            if(mode_code == -1)
            {
                  reader->raiseError(tr("column mode invalid"));
                  return false;
            }
            setColumnMode((SciDAVis::ColumnMode)mode_code);
            if(type_code != int(dataType()))
            {
                  reader->raiseError(tr("column type or mode invalid"));
                  return false;
            }
            // read plot designation
            str = attribs.value(reader->namespaceUri().toString(), "plot_designation").toString();
            int pd_code = SciDAVis::enumStringToValue(str, "PlotDesignation");
            if(str.isEmpty())
                  setPlotDesignation(SciDAVis::noDesignation);
            else if(pd_code == -1)
            {
                  reader->raiseError(tr("column plot designation invalid"));
                  return false;
            }
            else
                  setPlotDesignation((SciDAVis::PlotDesignation)pd_code);

            setComment("");
            if (rowCount() > 0)
                  removeRows(0, rowCount());          
            clearValidity();
            clearMasks();
            clearFormulas();
            // read child elements
            while (!reader->atEnd()) 
            {
                  reader->readNext();

                  if (reader->isEndElement()) break;

                  if (reader->isStartElement()) 
                  {
                        bool ret_val = true;
                        if (reader->name() == "comment")
                              ret_val = readCommentElement(reader);
                        else if(reader->name() == "input_filter")
                              ret_val = XmlReadInputFilter(reader);
                        else if(reader->name() == "output_filter")
                              ret_val = XmlReadOutputFilter(reader);
                        else if(reader->name() == "mask")
                              ret_val = XmlReadMask(reader);
                        else if(reader->name() == "formula")
                              ret_val = XmlReadFormula(reader);
                        else if(reader->name() == "row")
                              ret_val = XmlReadRow(reader);
                        else // unknown element
                        {
                              reader->raiseWarning(tr("unknown element '%1'").arg(reader->name().toString()));
                              if (!reader->skipToEndElement()) return false;
                        }
                        if(!ret_val)
                              return false;
                  } 
            }
      }
      else // no column element
            reader->raiseError(tr("no column element found"));

      return !reader->error();
}
                              
00467 bool Column::XmlReadInputFilter(XmlStreamReader * reader)
{
      Q_ASSERT(reader->isStartElement() && reader->name() == "input_filter");
      if (!reader->skipToNextTag()) return false;
      if (!d_column_private->inputFilter()->load(reader)) return false;
      if (!reader->skipToNextTag()) return false;
      Q_ASSERT(reader->isEndElement() && reader->name() == "input_filter");
      return true;
}

00477 bool Column::XmlReadOutputFilter(XmlStreamReader * reader)
{
      Q_ASSERT(reader->isStartElement() && reader->name() == "output_filter");
      if (!reader->skipToNextTag()) return false;
      if (!outputFilter()->load(reader)) return false;
      if (!reader->skipToNextTag()) return false;
      Q_ASSERT(reader->isEndElement() && reader->name() == "output_filter");
      return true;
}

00487 bool Column::XmlReadMask(XmlStreamReader * reader)
{
      Q_ASSERT(reader->isStartElement() && reader->name() == "mask");

      bool ok1, ok2;
      int start, end;
      start = reader->readAttributeInt("start_row", &ok1);
      end = reader->readAttributeInt("end_row", &ok2);
      if(!ok1 || !ok2) 
      {
            reader->raiseError(tr("invalid or missing start or end row"));
            return false;
      }
      setMasked(Interval<int>(start,end));
      if (!reader->skipToEndElement()) return false;

      return true;
}

00506 bool Column::XmlReadFormula(XmlStreamReader * reader)
{
      Q_ASSERT(reader->isStartElement() && reader->name() == "formula");

      bool ok1, ok2;
      int start, end;
      start = reader->readAttributeInt("start_row", &ok1);
      end = reader->readAttributeInt("end_row", &ok2);
      if(!ok1 || !ok2) 
      {
            reader->raiseError(tr("invalid or missing start or end row"));
            return false;
      }
      setFormula(Interval<int>(start,end), reader->readElementText());

      return true;
}

00524 bool Column::XmlReadRow(XmlStreamReader * reader)
{
      Q_ASSERT(reader->isStartElement() && reader->name() == "row");
      
      QString str;
      int type_code;

      QXmlStreamAttributes attribs = reader->attributes();
      // verfiy type
      str = attribs.value(reader->namespaceUri().toString(), "type").toString();
      type_code = SciDAVis::enumStringToValue(str, "ColumnDataType");
      if(str.isEmpty() || type_code == -1 || type_code != int(dataType()))
      {
            reader->raiseError(tr("invalid or missing row type"));
            return false;
      }
      
      bool ok;
      int index = reader->readAttributeInt("index", &ok);
      if(!ok)
      {
            reader->raiseError(tr("invalid or missing row index"));
            return false;
      }

      str = reader->readElementText();
      switch(dataType())
      {
            case SciDAVis::TypeDouble:
                  {
                        double value = str.toDouble(&ok);
                        if(!ok)
                        {
                              reader->raiseError(tr("invalid row value"));
                              return false;
                        }
                        setValueAt(index, value);
                        break;
                  }
            case SciDAVis::TypeQString:
                  setTextAt(index, str);
                  break;

            case SciDAVis::TypeQDateTime:
                  QDateTime date_time = QDateTime::fromString(str,"yyyy-dd-MM hh:mm:ss:zzz");
                  setDateTimeAt(index, date_time);
                  break;
      }

      str = attribs.value(reader->namespaceUri().toString(), "invalid").toString();
      if(str == "yes") setInvalid(index);


      return true;
}
00579 SciDAVis::ColumnDataType Column::dataType() const 
{ 
      return d_column_private->dataType(); 
}

00584 SciDAVis::ColumnMode Column::columnMode() const 
{ 
      return d_column_private->columnMode(); 
}
00588 int Column::rowCount() const 
{ 
      return d_column_private->rowCount(); 
}

00593 SciDAVis::PlotDesignation Column::plotDesignation() const
{ 
      return d_column_private->plotDesignation(); 
}

00598 AbstractSimpleFilter * Column::outputFilter() const 
{ 
      return d_column_private->outputFilter(); 
}

00603 bool Column::isInvalid(int row) const 
{ 
      return d_column_private->isInvalid(row); 
}

00608 bool Column::isInvalid(Interval<int> i) const 
{ 
      return d_column_private->isInvalid(i); 
}

00613 QList< Interval<int> > Column::invalidIntervals() const 
{ 
      return d_column_private->invalidIntervals(); 
}

00618 bool Column::isMasked(int row) const 
{ 
      return d_column_private->isMasked(row); 
}

00623 bool Column::isMasked(Interval<int> i) const 
{ 
      return d_column_private->isMasked(i); 
}

00628 QList< Interval<int> > Column::maskedIntervals() const 
{ 
      return d_column_private->maskedIntervals(); 
}

00633 QString Column::formula(int row) const 
{ 
      return d_column_private->formula(row); 
}

00638 QList< Interval<int> > Column::formulaIntervals() const 
{ 
      return d_column_private->formulaIntervals(); 
}

void Column::notifyDisplayChange()
{
      emit dataChanged(this); // all cells must be repainted
      emit aspectDescriptionChanged(this); // the icon for the type changed
}

00649 QString ColumnStringIO::textAt(int row) const
{
      if (d_setting)
            return d_to_set;
      else
            return d_owner->d_column_private->outputFilter()->output(0)->textAt(row);
}

void ColumnStringIO::setTextAt(int row, const QString &value)
{
      d_setting = true;
      d_to_set = value;
      d_owner->copy(d_owner->d_column_private->inputFilter()->output(0), 0, row, 1);
      d_setting = false;
      d_to_set.clear();
}

00666 bool ColumnStringIO::copy(const AbstractColumn *other) {
      if (other->columnMode() != SciDAVis::Text) return false;
      d_owner->d_column_private->inputFilter()->input(0,other);
      d_owner->copy(d_owner->d_column_private->inputFilter()->output(0));
      d_owner->d_column_private->inputFilter()->input(0,this);
      return true;
}

00674 bool ColumnStringIO::copy(const AbstractColumn *source, int source_start, int dest_start, int num_rows) {
      if (source->columnMode() != SciDAVis::Text) return false;
      d_owner->d_column_private->inputFilter()->input(0,source);
      d_owner->copy(d_owner->d_column_private->inputFilter()->output(0), source_start, dest_start, num_rows);
      d_owner->d_column_private->inputFilter()->input(0,this);
      return true;
}

00682 void ColumnStringIO::replaceTexts(int start_row, const QStringList &texts) {
      Column tmp("tmp", texts);
      copy(&tmp, 0, start_row, texts.size());
}

Generated by  Doxygen 1.6.0   Back to index