/***************************************************************************
    File                 : columncommands.cpp
    Project              : SciDAVis
    Description          : Commands to be called by Column to modify Column::Private
    --------------------------------------------------------------------
    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 "ColumnPrivate.h"
#include "columncommands.h"

///////////////////////////////////////////////////////////////////////////
// class ColumnSetModeCmd
///////////////////////////////////////////////////////////////////////////
ColumnSetModeCmd::ColumnSetModeCmd(Column::Private * col, SciDAVis::ColumnMode mode,
		AbstractFilter *conversion_filter, QUndoCommand * parent )
: QUndoCommand( parent ), d_col(col), d_mode(mode), d_conversion_filter(conversion_filter)
{
	setText(QObject::tr("%1: change column type").arg(col->name()));
	d_undone = false;
	d_executed = false;
}

ColumnSetModeCmd::~ColumnSetModeCmd()
{
	if(d_undone)
	{
		if(d_new_data != d_old_data)
		{
			if(d_new_type == SciDAVis::TypeDouble)
				delete static_cast< QVector<double>* >(d_new_data);
			else if(d_new_type == SciDAVis::TypeQString)
				delete static_cast< QStringList* >(d_new_data);
			else if(d_new_type == SciDAVis::TypeQDateTime)
				delete static_cast< QList<QDateTime>* >(d_new_data);
		}
	}
	else
	{
		if(d_new_data != d_old_data)
		{
			if(d_old_type == SciDAVis::TypeDouble)
				delete static_cast< QVector<double>* >(d_old_data);
			else if(d_old_type == SciDAVis::TypeQString)
				delete static_cast< QStringList* >(d_old_data);
			else if(d_old_type == SciDAVis::TypeQDateTime)
				delete static_cast< QList<QDateTime>* >(d_old_data);
		}
	}
	if (d_conversion_filter)
		delete d_conversion_filter;
}

void ColumnSetModeCmd::redo()
{
	if(!d_executed)
	{
		// save old values
		d_old_mode = d_col->columnMode();	
		d_old_type = d_col->dataType();
		d_old_data = d_col->dataPointer();
		d_old_in_filter = d_col->inputFilter();
		d_old_out_filter = d_col->outputFilter();
		d_old_validity = d_col->validityAttribute();

		// do the conversion
		d_col->setColumnMode(d_mode, d_conversion_filter);

		// save new values
		d_new_type = d_col->dataType();
		d_new_data = d_col->dataPointer();
		d_new_in_filter = d_col->inputFilter();
		d_new_out_filter = d_col->outputFilter();
		d_new_validity = d_col->validityAttribute();
		d_executed = true;
	}
	else
	{
		// set to saved new values
		d_col->replaceModeData(d_mode, d_new_type, d_new_data, d_new_in_filter, d_new_out_filter, d_new_validity);
	}
	d_undone = false;
}

void ColumnSetModeCmd::undo()
{
	// reset to old values
	d_col->replaceModeData(d_old_mode, d_old_type, d_old_data, d_old_in_filter, d_old_out_filter, d_old_validity);

	d_undone = true;
}

///////////////////////////////////////////////////////////////////////////
// end of class ColumnSetModeCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnFullCopyCmd
///////////////////////////////////////////////////////////////////////////
ColumnFullCopyCmd::ColumnFullCopyCmd(Column::Private * col, const AbstractColumn * src, QUndoCommand * parent )
: QUndoCommand( parent ), d_col(col), d_src(src), d_backup(0), d_backup_owner(0)
{
	setText(QObject::tr("%1: change cell value(s)").arg(col->name()));
}

ColumnFullCopyCmd::~ColumnFullCopyCmd()
{
	delete d_backup;
	delete d_backup_owner;
}

void ColumnFullCopyCmd::redo()
{
	if(d_backup == 0)
	{
		d_backup_owner = new Column("temp", d_src->columnMode());
		d_backup = new Column::Private(d_backup_owner, d_src->columnMode()); 
		d_backup->copy(d_col);
		d_col->copy(d_src);
	}
	else
	{
		// swap data + validity of orig. column and backup
		IntervalAttribute<bool> val_temp = d_col->invalidIntervals();
		void * data_temp = d_col->dataPointer();
		d_col->replaceData(d_backup->dataPointer(), d_backup->validityAttribute());
		d_backup->replaceData(data_temp, val_temp);
	}
}

void ColumnFullCopyCmd::undo()
{
	// swap data + validity of orig. column and backup
	IntervalAttribute<bool> val_temp = d_col->validityAttribute();
	void * data_temp = d_col->dataPointer();
	d_col->replaceData(d_backup->dataPointer(), d_backup->validityAttribute());
	d_backup->replaceData(data_temp, val_temp);
}

///////////////////////////////////////////////////////////////////////////
// end of class ColumnFullCopyCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnPartialCopyCmd
///////////////////////////////////////////////////////////////////////////
ColumnPartialCopyCmd::ColumnPartialCopyCmd(Column::Private * col, const AbstractColumn * src, int src_start, int dest_start, int num_rows, QUndoCommand * parent )
: QUndoCommand( parent ), d_col(col), d_src(src), d_src_start(src_start), d_dest_start(dest_start), d_num_rows(num_rows), d_col_backup(0), d_src_backup(0), d_col_backup_owner(0), d_src_backup_owner(0)
{
	setText(QObject::tr("%1: change cell value(s)").arg(col->name()));
}

ColumnPartialCopyCmd::~ColumnPartialCopyCmd()
{
	delete d_src_backup;
	delete d_col_backup;
	delete d_src_backup_owner;
	delete d_col_backup_owner;
}

void ColumnPartialCopyCmd::redo()
{
	if(d_src_backup == 0)
	{
		// copy the relevant rows of source and destination column into backup columns
		d_src_backup_owner = new Column("temp", d_col->columnMode());
		d_src_backup = new Column::Private(d_src_backup_owner, d_col->columnMode());
		d_src_backup->copy(d_src, d_src_start, 0, d_num_rows);
		d_col_backup_owner = new Column("temp", d_col->columnMode());
		d_col_backup = new Column::Private(d_col_backup_owner, d_col->columnMode());
		d_col_backup->copy(d_col, d_dest_start, 0, d_num_rows);
		d_old_row_count = d_col->rowCount();
		d_old_validity = d_col->validityAttribute();
	}
	d_col->copy(d_src_backup, 0, d_dest_start, d_num_rows);
}

void ColumnPartialCopyCmd::undo()
{
	d_col->copy(d_col_backup, 0, d_dest_start, d_num_rows);
	d_col->resizeTo(d_old_row_count);
	d_col->replaceData(d_col->dataPointer(), d_old_validity);
}

///////////////////////////////////////////////////////////////////////////
// end of class ColumnPartialCopyCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnInsertEmptyRowsCmd
///////////////////////////////////////////////////////////////////////////
ColumnInsertEmptyRowsCmd::ColumnInsertEmptyRowsCmd(Column::Private * col, int before, int count, QUndoCommand * parent )
: QUndoCommand( parent ), d_col(col), d_before(before), d_count(count)
{
	setText(QObject::tr("%1: insert %2 row(s)").arg(col->name()).arg(count));
}

ColumnInsertEmptyRowsCmd::~ColumnInsertEmptyRowsCmd()
{
}

void ColumnInsertEmptyRowsCmd::redo()
{
	d_col->insertRows(d_before, d_count);
}

void ColumnInsertEmptyRowsCmd::undo()
{
	d_col->removeRows(d_before, d_count);
}

///////////////////////////////////////////////////////////////////////////
// end of class ColumnInsertEmptyRowsCmd
///////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////
// class ColumnRemoveRowsCmd
///////////////////////////////////////////////////////////////////////////
ColumnRemoveRowsCmd::ColumnRemoveRowsCmd(Column::Private * col, int first, int count, QUndoCommand * parent )
: QUndoCommand( parent ), d_col(col), d_first(first), d_count(count), d_backup(0)
{
	setText(QObject::tr("%1: remove %2 row(s)").arg(col->name()).arg(count));
}

ColumnRemoveRowsCmd::~ColumnRemoveRowsCmd()
{
	delete d_backup;
	delete d_backup_owner;
}

void ColumnRemoveRowsCmd::redo()
{
	if(d_backup == 0)
	{
		if(d_first >= d_col->rowCount())
			d_data_row_count = 0;
		else if(d_first + d_count > d_col->rowCount()) 
			d_data_row_count = d_col->rowCount() - d_first;
		else
			d_data_row_count = d_count;

		d_old_size = d_col->rowCount();
		d_backup_owner = new Column("temp", d_col->columnMode());
		d_backup = new Column::Private(d_backup_owner, d_col->columnMode()); 
		d_backup->copy(d_col, d_first, 0, d_data_row_count);
		d_masking = d_col->maskingAttribute();
		d_formulas = d_col->formulaAttribute();
	}
	d_col->removeRows(d_first, d_count);
}

void ColumnRemoveRowsCmd::undo()
{
	d_col->insertRows(d_first, d_count);
	d_col->copy(d_backup, 0, d_first, d_data_row_count);
	d_col->resizeTo(d_old_size);
	d_col->replaceMasking(d_masking);
	d_col->replaceFormulas(d_formulas);
}

///////////////////////////////////////////////////////////////////////////
// end of class ColumnRemoveRowsCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnSetPlotDesignationCmd
///////////////////////////////////////////////////////////////////////////
ColumnSetPlotDesignationCmd::ColumnSetPlotDesignationCmd( Column::Private * col, SciDAVis::PlotDesignation pd , QUndoCommand * parent )
: QUndoCommand( parent ), d_col(col), d_new_pd(pd)
{
	setText(QObject::tr("%1: set plot designation").arg(col->name()));
}

ColumnSetPlotDesignationCmd::~ColumnSetPlotDesignationCmd()
{
}

void ColumnSetPlotDesignationCmd::redo()
{
	d_old_pd = d_col->plotDesignation();
	d_col->setPlotDesignation(d_new_pd);
}

void ColumnSetPlotDesignationCmd::undo()
{
	d_col->setPlotDesignation(d_old_pd);
}

///////////////////////////////////////////////////////////////////////////
// end of class ColumnSetPlotDesignationCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnClearCmd
///////////////////////////////////////////////////////////////////////////
ColumnClearCmd::ColumnClearCmd(Column::Private * col, QUndoCommand * parent )
: QUndoCommand( parent ), d_col(col)
{
	setText(QObject::tr("%1: clear column").arg(col->name()));
	d_empty_data = 0;
	d_undone = false;
}

ColumnClearCmd::~ColumnClearCmd()
{
	if(d_undone)
	{
		if(d_type == SciDAVis::TypeDouble)
			delete static_cast< QVector<double>* >(d_empty_data);
		else if(d_type == SciDAVis::TypeQString)
			delete static_cast< QStringList* >(d_empty_data);
		else if(d_type == SciDAVis::TypeQDateTime)
			delete static_cast< QList<QDateTime>* >(d_empty_data);
	}
	else
	{
		if(d_type == SciDAVis::TypeDouble)
			delete static_cast< QVector<double>* >(d_data);
		else if(d_type == SciDAVis::TypeQString)
			delete static_cast< QStringList* >(d_data);
		else if(d_type == SciDAVis::TypeQDateTime)
			delete static_cast< QList<QDateTime>* >(d_data);
	}
}

void ColumnClearCmd::redo()
{
	if(!d_empty_data)
	{
		d_type = d_col->dataType();
		switch(d_type)
		{
			case SciDAVis::TypeDouble:
				d_empty_data = new QVector<double>();
				break;
			case SciDAVis::TypeQDateTime:
				d_empty_data = new QList<QDateTime>();
				break;
			case SciDAVis::TypeQString:
				d_empty_data = new QStringList();
				break;
		}
		d_data = d_col->dataPointer();
		d_validity = d_col->validityAttribute();
	}
	d_col->replaceData(d_empty_data, IntervalAttribute<bool>());
	d_undone = false;
}

void ColumnClearCmd::undo()
{
	d_col->replaceData(d_data, d_validity);
	d_undone = true;
}

///////////////////////////////////////////////////////////////////////////
// end of class ColumnClearCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnClearValidityCmd
///////////////////////////////////////////////////////////////////////////
ColumnClearValidityCmd::ColumnClearValidityCmd(Column::Private * col, QUndoCommand * parent )
: QUndoCommand( parent ), d_col(col)
{
	setText(QObject::tr("%1: mark all cells valid").arg(col->name()));
	d_copied = false;
}

ColumnClearValidityCmd::~ColumnClearValidityCmd()
{
}

void ColumnClearValidityCmd::redo()
{
	if(!d_copied)
	{
		d_validity = d_col->validityAttribute();
		d_copied = true;
	}
	d_col->clearValidity();
}

void ColumnClearValidityCmd::undo()
{
	d_col->replaceData(d_col->dataPointer(), d_validity);
}

///////////////////////////////////////////////////////////////////////////
// end of class ColumnClearValidityCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnClearMasksCmd
///////////////////////////////////////////////////////////////////////////
ColumnClearMasksCmd::ColumnClearMasksCmd(Column::Private * col, QUndoCommand * parent )
: QUndoCommand( parent ), d_col(col)
{
	setText(QObject::tr("%1: clear masks").arg(col->name()));
	d_copied = false;
}

ColumnClearMasksCmd::~ColumnClearMasksCmd()
{
}

void ColumnClearMasksCmd::redo()
{
	if(!d_copied)
	{
		d_masking = d_col->maskingAttribute();
		d_copied = true;
	}
	d_col->clearMasks();
}

void ColumnClearMasksCmd::undo()
{
	d_col->replaceMasking(d_masking);
}

///////////////////////////////////////////////////////////////////////////
// end of class ColumnClearMasksCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnSetInvalidCmd
///////////////////////////////////////////////////////////////////////////
ColumnSetInvalidCmd::ColumnSetInvalidCmd(Column::Private * col, Interval<int> interval, bool invalid, QUndoCommand * parent )
: QUndoCommand( parent ), d_col(col), d_interval(interval), d_invalid(invalid)
{
	if(invalid)
		setText(QObject::tr("%1: mark cells invalid").arg(col->name()));
	else
		setText(QObject::tr("%1: mark cells valid").arg(col->name()));
	d_copied = false;
}

ColumnSetInvalidCmd::~ColumnSetInvalidCmd()
{
}

void ColumnSetInvalidCmd::redo()
{
	if(!d_copied)
	{
		d_validity = d_col->validityAttribute();
		d_copied = true;
	}
	d_col->setInvalid(d_interval, d_invalid);
}

void ColumnSetInvalidCmd::undo()
{
	d_col->replaceData(d_col->dataPointer(), d_validity);
}

///////////////////////////////////////////////////////////////////////////
// end of class ColumnSetInvalidCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnSetMaskedCmd
///////////////////////////////////////////////////////////////////////////
ColumnSetMaskedCmd::ColumnSetMaskedCmd(Column::Private * col, Interval<int> interval, bool masked, QUndoCommand * parent )
: QUndoCommand( parent ), d_col(col), d_interval(interval), d_masked(masked)
{
	if(masked)
		setText(QObject::tr("%1: mask cells").arg(col->name()));
	else
		setText(QObject::tr("%1: unmask cells").arg(col->name()));
	d_copied = false;
}

ColumnSetMaskedCmd::~ColumnSetMaskedCmd()
{
}

void ColumnSetMaskedCmd::redo()
{
	if(!d_copied)
	{
		d_masking = d_col->maskingAttribute();
		d_copied = true;
	}
	d_col->setMasked(d_interval, d_masked);
}

void ColumnSetMaskedCmd::undo()
{
	d_col->replaceMasking(d_masking);
}

///////////////////////////////////////////////////////////////////////////
// end of class ColumnSetMaskedCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnSetFormulaCmd
///////////////////////////////////////////////////////////////////////////
ColumnSetFormulaCmd::ColumnSetFormulaCmd(Column::Private * col, Interval<int> interval, const QString& formula, QUndoCommand * parent )
: QUndoCommand( parent ), d_col(col), d_interval(interval), d_formula(formula)
{
	setText(QObject::tr("%1: set cell formula").arg(col->name()));
	d_copied = false;
}

ColumnSetFormulaCmd::~ColumnSetFormulaCmd()
{
}

void ColumnSetFormulaCmd::redo()
{
	if(!d_copied)
	{
		d_formulas = d_col->formulaAttribute();
		d_copied = true;
	}
	d_col->setFormula(d_interval, d_formula);
}

void ColumnSetFormulaCmd::undo()
{
	d_col->replaceFormulas(d_formulas);
}

///////////////////////////////////////////////////////////////////////////
// end of class ColumnSetFormulaCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnClearFormulasCmd
///////////////////////////////////////////////////////////////////////////
ColumnClearFormulasCmd::ColumnClearFormulasCmd(Column::Private * col, QUndoCommand * parent )
: QUndoCommand( parent ), d_col(col)
{
	setText(QObject::tr("%1: clear all formulas").arg(col->name()));
	d_copied = false;
}

ColumnClearFormulasCmd::~ColumnClearFormulasCmd()
{
}

void ColumnClearFormulasCmd::redo()
{
	if(!d_copied)
	{
		d_formulas = d_col->formulaAttribute();
		d_copied = true;
	}
	d_col->clearFormulas();
}

void ColumnClearFormulasCmd::undo()
{
	d_col->replaceFormulas(d_formulas);
}

///////////////////////////////////////////////////////////////////////////
// end of class ColumnClearFormulasCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnSetTextCmd
///////////////////////////////////////////////////////////////////////////
ColumnSetTextCmd::ColumnSetTextCmd(Column::Private * col, int row, const QString& new_value, QUndoCommand * parent )
: QUndoCommand( parent ), d_col(col), d_row(row), d_new_value(new_value)
{
	setText(QObject::tr("%1: set text for row %2").arg(col->name()).arg(row));
}

ColumnSetTextCmd::~ColumnSetTextCmd()
{
}

void ColumnSetTextCmd::redo()
{
	d_old_value = d_col->textAt(d_row);
	d_row_count = d_col->rowCount();
	d_validity = d_col->validityAttribute();
	d_col->setTextAt(d_row, d_new_value);
}

void ColumnSetTextCmd::undo()
{
	d_col->setTextAt(d_row, d_old_value);
	d_col->resizeTo(d_row_count);
	d_col->replaceData(d_col->dataPointer(), d_validity);
}

///////////////////////////////////////////////////////////////////////////
// end of class ColumnSetTextCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnSetValueCmd
///////////////////////////////////////////////////////////////////////////
ColumnSetValueCmd::ColumnSetValueCmd(Column::Private * col, int row, double new_value, QUndoCommand * parent )
: QUndoCommand( parent ), d_col(col), d_row(row), d_new_value(new_value)
{
	setText(QObject::tr("%1: set value for row %2").arg(col->name()).arg(row));
}

ColumnSetValueCmd::~ColumnSetValueCmd()
{
}

void ColumnSetValueCmd::redo()
{
	d_old_value = d_col->valueAt(d_row);
	d_row_count = d_col->rowCount();
	d_validity = d_col->validityAttribute();
	d_col->setValueAt(d_row, d_new_value);
}

void ColumnSetValueCmd::undo()
{
	d_col->setValueAt(d_row, d_old_value);
	d_col->resizeTo(d_row_count);
	d_col->replaceData(d_col->dataPointer(), d_validity);
}

///////////////////////////////////////////////////////////////////////////
// end of class ColumnSetValueCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnSetDateTimeCmd
///////////////////////////////////////////////////////////////////////////
ColumnSetDateTimeCmd::ColumnSetDateTimeCmd(Column::Private * col, int row, const QDateTime& new_value, QUndoCommand * parent )
: QUndoCommand( parent ), d_col(col), d_row(row), d_new_value(new_value)
{
	setText(QObject::tr("%1: set value for row %2").arg(col->name()).arg(row));
}

ColumnSetDateTimeCmd::~ColumnSetDateTimeCmd()
{
}

void ColumnSetDateTimeCmd::redo()
{
	d_old_value = d_col->dateTimeAt(d_row);
	d_row_count = d_col->rowCount();
	d_validity = d_col->validityAttribute();
	d_col->setDateTimeAt(d_row, d_new_value);
}

void ColumnSetDateTimeCmd::undo()
{
	d_col->setDateTimeAt(d_row, d_old_value);
	d_col->resizeTo(d_row_count);
	d_col->replaceData(d_col->dataPointer(), d_validity);
}

///////////////////////////////////////////////////////////////////////////
// end of class ColumnSetDateTimeCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnReplaceTextsCmd
///////////////////////////////////////////////////////////////////////////
ColumnReplaceTextsCmd::ColumnReplaceTextsCmd(Column::Private * col, int first, const QStringList& new_values, QUndoCommand * parent )
 : QUndoCommand( parent ), d_col(col), d_first(first), d_new_values(new_values)
{
	setText(QObject::tr("%1: replace the texts for rows %2 to %3").arg(col->name()).arg(first).arg(first + new_values.count() -1));
	d_copied = false;
}

ColumnReplaceTextsCmd::~ColumnReplaceTextsCmd()
{
}

void ColumnReplaceTextsCmd::redo()
{
	if(!d_copied)
	{
		d_old_values = static_cast< QStringList* >(d_col->dataPointer())->mid(d_first, d_new_values.count());
		d_row_count = d_col->rowCount();
		d_validity = d_col->validityAttribute();
		d_copied = true;
	}
	d_col->replaceTexts(d_first, d_new_values);
}

void ColumnReplaceTextsCmd::undo()
{
	d_col->replaceTexts(d_first, d_old_values);
	d_col->resizeTo(d_row_count);
	d_col->replaceData(d_col->dataPointer(), d_validity);
}

///////////////////////////////////////////////////////////////////////////
// end of class ColumnReplaceTextsCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnReplaceValuesCmd
///////////////////////////////////////////////////////////////////////////
ColumnReplaceValuesCmd::ColumnReplaceValuesCmd(Column::Private * col, int first, const QVector<double>& new_values, QUndoCommand * parent )
 : QUndoCommand( parent ), d_col(col), d_first(first), d_new_values(new_values)
{
	setText(QObject::tr("%1: replace the values for rows %2 to %3").arg(col->name()).arg(first).arg(first + new_values.count() -1));
	d_copied = false;
}

ColumnReplaceValuesCmd::~ColumnReplaceValuesCmd()
{
}

void ColumnReplaceValuesCmd::redo()
{
	if(!d_copied)
	{
		d_old_values = static_cast< QVector<double>* >(d_col->dataPointer())->mid(d_first, d_new_values.count());
		d_row_count = d_col->rowCount();
		d_validity = d_col->validityAttribute();
		d_copied = true;
	}
	d_col->replaceValues(d_first, d_new_values);
}

void ColumnReplaceValuesCmd::undo()
{
	d_col->replaceValues(d_first, d_old_values);
	d_col->resizeTo(d_row_count);
	d_col->replaceData(d_col->dataPointer(), d_validity);
}

///////////////////////////////////////////////////////////////////////////
// end of class ColumnReplaceValuesCmd
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// class ColumnReplaceDateTimesCmd
///////////////////////////////////////////////////////////////////////////
ColumnReplaceDateTimesCmd::ColumnReplaceDateTimesCmd(Column::Private * col, int first, const QList<QDateTime>& new_values, QUndoCommand * parent )
 : QUndoCommand( parent ), d_col(col), d_first(first), d_new_values(new_values)
{
	setText(QObject::tr("%1: replace the values for rows %2 to %3").arg(col->name()).arg(first).arg(first + new_values.count() -1));
	d_copied = false;
}

ColumnReplaceDateTimesCmd::~ColumnReplaceDateTimesCmd()
{
}

void ColumnReplaceDateTimesCmd::redo()
{
	if(!d_copied)
	{
		d_old_values = static_cast< QList<QDateTime>* >(d_col->dataPointer())->mid(d_first, d_new_values.count());
		d_row_count = d_col->rowCount();
		d_validity = d_col->validityAttribute();
		d_copied = true;
	}
	d_col->replaceDateTimes(d_first, d_new_values);
}

void ColumnReplaceDateTimesCmd::undo()
{
	d_col->replaceDateTimes(d_first, d_old_values);
	d_col->replaceData(d_col->dataPointer(), d_validity);
	d_col->resizeTo(d_row_count);
}

///////////////////////////////////////////////////////////////////////////
// end of class ColumnReplaceDateTimesCmd
///////////////////////////////////////////////////////////////////////////



