38#include "kspread_doc.h"
39#include "kspread_locale.h"
40#include "kspread_sheet.h"
41#include "kspread_undo.h"
42#include "kspread_value.h"
43#include "valueconverter.h"
44#include "kspread_autofill.h"
48TQStringList *AutoFillSequenceItem::month = 0L;
49TQStringList *AutoFillSequenceItem::shortMonth = 0L;
50TQStringList *AutoFillSequenceItem::day = 0L;
51TQStringList *AutoFillSequenceItem::shortDay = 0L;
52TQStringList *AutoFillSequenceItem::other = 0L;
59AutoFillDeltaSequence::AutoFillDeltaSequence( AutoFillSequence *_first, AutoFillSequence *_next )
63 if ( _first->count() != _next->count() )
69 m_sequence =
new TQMemArray<double> ( _first->count() );
71 AutoFillSequenceItem *item = _first->getFirst();
72 AutoFillSequenceItem *item2 = _next->getFirst();
75 for ( i = 0; i < _first->count(); i++ )
78 if ( !item->getDelta( item2, d ) )
83 m_sequence->at( i++ ) = d;
84 item2 = _next->getNext();
85 item = _first->getNext();
89AutoFillDeltaSequence::~AutoFillDeltaSequence()
94bool AutoFillDeltaSequence::equals( AutoFillDeltaSequence *_delta )
96 if ( m_sequence == 0L )
98 if ( _delta->getSequence() == 0L )
100 if ( m_sequence->size() != _delta->getSequence()->size() )
103 for (
unsigned int i = 0; i < m_sequence->size(); i++ )
105 if ( m_sequence->at( i ) != _delta->getSequence()->at( i ) )
112double AutoFillDeltaSequence::getItemDelta(
int _pos )
114 if ( m_sequence == 0L )
117 return m_sequence->at( _pos );
126AutoFillSequenceItem::AutoFillSequenceItem(
int _i )
132AutoFillSequenceItem::AutoFillSequenceItem(
double _d )
138AutoFillSequenceItem::AutoFillSequenceItem(
const TQString &_str )
145 month =
new TQStringList();
146 month->append( i18n(
"January") );
147 month->append( i18n(
"February") );
148 month->append( i18n(
"March") );
149 month->append( i18n(
"April") );
150 month->append( i18n(
"May") );
151 month->append( i18n(
"June") );
152 month->append( i18n(
"July") );
153 month->append( i18n(
"August") );
154 month->append( i18n(
"September") );
155 month->append( i18n(
"October") );
156 month->append( i18n(
"November") );
157 month->append( i18n(
"December") );
160 if ( shortMonth == 0L )
162 shortMonth =
new TQStringList();
163 shortMonth->append( i18n(
"Jan") );
164 shortMonth->append( i18n(
"Feb") );
165 shortMonth->append( i18n(
"Mar") );
166 shortMonth->append( i18n(
"Apr") );
167 shortMonth->append( i18n(
"May short",
"May") );
168 shortMonth->append( i18n(
"Jun") );
169 shortMonth->append( i18n(
"Jul") );
170 shortMonth->append( i18n(
"Aug") );
171 shortMonth->append( i18n(
"Sep") );
172 shortMonth->append( i18n(
"Oct") );
173 shortMonth->append( i18n(
"Nov") );
174 shortMonth->append( i18n(
"Dec") );
179 day =
new TQStringList();
180 day->append( i18n(
"Monday") );
181 day->append( i18n(
"Tuesday") );
182 day->append( i18n(
"Wednesday") );
183 day->append( i18n(
"Thursday") );
184 day->append( i18n(
"Friday") );
185 day->append( i18n(
"Saturday") );
186 day->append( i18n(
"Sunday") );
189 if ( shortDay == 0L )
191 shortDay =
new TQStringList();
192 shortDay->append( i18n(
"Mon") );
193 shortDay->append( i18n(
"Tue") );
194 shortDay->append( i18n(
"Wed") );
195 shortDay->append( i18n(
"Thu") );
196 shortDay->append( i18n(
"Fri") );
197 shortDay->append( i18n(
"Sat") );
198 shortDay->append( i18n(
"Sun") );
204 TDEConfig *config = Factory::global()->config();
205 config->setGroup(
"Parameters" );
206 other=
new TQStringList(config->readListEntry(
"Other list"));
209 if ( month->find( _str ) != month->end() )
215 if ( shortMonth->find( _str ) != shortMonth->end() )
221 if ( day->find( _str ) != day->end() )
227 if ( shortDay->find( _str ) != shortDay->end() )
233 if( other->find(_str)!=other->end())
237 m_OtherEnd=other->count();
238 int index= other->findIndex(_str);
240 for ( TQStringList::Iterator it = other->find(_str); it != other->end();++it )
249 index= other->findIndex(_str);
250 for ( TQStringList::Iterator it = other->find(_str); it != other->begin();--it )
262 if ( m_String[0] ==
'=' )
266bool AutoFillSequenceItem::getDelta( AutoFillSequenceItem *seq,
double &_delta )
268 if ( seq->getType() != m_Type )
274 _delta = (double)( seq->getIValue() - m_IValue );
277 _delta = seq->getDValue() - m_DValue;
281 if ( m_String == seq->getString() )
289 int i = month->findIndex( m_String );
290 int j = month->findIndex( seq->getString() );
296 _delta = ( double )( k - i );
302 int i = shortMonth->findIndex( m_String );
303 int j = shortMonth->findIndex( seq->getString() );
309 _delta = ( double )( k - i );
315 int i = day->findIndex( m_String );
316 int j = day->findIndex( seq->getString() );
322 _delta = ( double )( k - i );
323 kdDebug() << m_String <<
" i: " << i <<
" j: " << j <<
" k: " << k <<
" delta: " << _delta << endl;
329 int i = shortDay->findIndex( m_String );
330 int j = shortDay->findIndex( seq->getString() );
336 _delta = ( double )( k - i );
341 if( m_OtherEnd!= seq->getIOtherEnd() || m_OtherBegin!= seq->getIOtherBegin())
343 int i = other->findIndex( m_String );
344 int j = other->findIndex( seq->getString() );
347 k += (m_OtherEnd - m_OtherBegin - 1);
351 _delta = ( double )( k - i );
359TQString AutoFillSequenceItem::getSuccessor(
int _no,
double _delta )
365 erg.sprintf(
"%i", m_IValue + _no * (
int)_delta );
368 erg.sprintf(
"%f", m_DValue + (
double)_no * _delta );
376 int i = month->findIndex( m_String );
377 int j = i + _no * (int) _delta;
380 int k = j % month->count();
381 erg = (*month->at( k ));
386 int i = shortMonth->findIndex( m_String );
387 int j = i + _no * (int) _delta;
389 j += shortMonth->count();
390 int k = j % shortMonth->count();
391 erg = (*shortMonth->at( k ));
396 int i = day->findIndex( m_String );
397 int j = i + _no * (int) _delta;
400 int k = j % day->count();
401 erg = (*day->at( k ));
406 int i = shortDay->findIndex( m_String );
407 int j = i + _no * (int) _delta;
409 j += shortDay->count();
410 int k = j % shortDay->count();
411 erg = (*shortDay->at( k ));
416 int i = other->findIndex( m_String )-(m_OtherBegin+1);
417 int j = i + _no * (int) _delta;
418 int k = j % (m_OtherEnd - m_OtherBegin-1);
419 erg = (*other->at( (k+m_OtherBegin+1) ));
427 return TQString( erg );
430TQString AutoFillSequenceItem::getPredecessor(
int _no,
double _delta )
436 erg.sprintf(
"%i", m_IValue - _no * (
int)_delta );
439 erg.sprintf(
"%f", m_DValue - (
double)_no * _delta );
447 int i = month->findIndex( m_String );
448 int j = i - _no * (int) _delta;
451 int k = j % month->count();
452 erg = (*month->at( k ));
457 int i = shortMonth->findIndex( m_String );
458 int j = i - _no * (int) _delta;
460 j += shortMonth->count();
461 int k = j % shortMonth->count();
462 erg = (*shortMonth->at( k ));
467 int i = day->findIndex( m_String );
468 int j = i - _no * (int) _delta;
471 int k = j % day->count();
472 erg = (*day->at( k ));
477 int i = shortDay->findIndex( m_String );
478 int j = i - _no * (int) _delta;
480 j += shortDay->count();
481 int k = j % shortDay->count();
482 erg = (*shortDay->at( k ));
487 int i = other->findIndex( m_String ) - (m_OtherBegin + 1);
488 int j = i - _no * (int) _delta;
490 j += (m_OtherEnd - m_OtherBegin - 1);
491 int k = j % (m_OtherEnd - m_OtherBegin - 1);
492 erg = (*other->at( (k + m_OtherBegin + 1) ));
500 return TQString( erg );
509AutoFillSequence::AutoFillSequence(
Cell *_cell )
511 sequence.setAutoDelete(
true );
516 sequence.append(
new AutoFillSequenceItem( d ) );
522 sequence.append(
new AutoFillSequenceItem( (
int)_cell->
value().
asFloat()) );
525 sequence.append(
new AutoFillSequenceItem(_cell->
value().
asFloat() ) );
527 else if ( !_cell->
text().isEmpty() )
528 sequence.append(
new AutoFillSequenceItem( _cell->
text() ) );
531bool AutoFillSequence::matches( AutoFillSequence* _seq, AutoFillDeltaSequence *_delta )
533 AutoFillDeltaSequence delta(
this, _seq );
537 if ( delta.equals( _delta ) )
543void AutoFillSequence::fillCell(
Cell *src,
Cell *dest, AutoFillDeltaSequence *delta,
int _block,
bool down )
548 if ( sequence.first() != 0L && sequence.first()->getType() == AutoFillSequenceItem::FORMULA )
550 TQString f = dest->decodeFormula( sequence.first()->getString() );
556 AutoFillSequenceItem *item;
560 for ( item = sequence.first(); item != 0L; item = sequence.next() )
561 erg += item->getSuccessor( _block, delta->getItemDelta( i++ ) );
565 for ( item = sequence.first(); item != 0L; item = sequence.next() )
566 erg += item->getPredecessor( _block, delta->getItemDelta( i++ ) );
579void Sheet::autofill( TQRect &src, TQRect &dest )
586 setRegionPaintDirty( dest );
588 doc()->emitBeginOperation();
590 if ( !doc()->undoLocked() )
592 UndoAutofill *undo =
new UndoAutofill( doc(),
this, dest );
593 doc()->addCommand( undo );
598 enableScrollBarUpdates(
false);
601 if ( src.left() == dest.left() && src.right() < dest.right() )
603 for (
int y = src.top(); y <= src.bottom(); y++ )
606 TQPtrList<Cell> destList;
607 for ( x = src.right() + 1; x <= dest.right(); x++ )
608 destList.append( nonDefaultCell( x, y ) );
609 TQPtrList<Cell> srcList;
610 for ( x = src.left(); x <= src.right(); x++ )
611 srcList.append( cellAt( x, y ) );
612 TQPtrList<AutoFillSequence> seqList;
613 seqList.setAutoDelete(
true );
614 for ( x = src.left(); x <= src.right(); x++ )
615 seqList.append(
new AutoFillSequence( cellAt( x, y ) ) );
616 fillSequence( srcList, destList, seqList );
621 if ( src.top() == dest.top() && src.bottom() < dest.bottom() )
623 for (
int x = src.left(); x <= dest.right(); x++ )
626 TQPtrList<Cell> destList;
627 for ( y = src.bottom() + 1; y <= dest.bottom(); y++ )
628 destList.append( nonDefaultCell( x, y ) );
629 TQPtrList<Cell> srcList;
630 for ( y = src.top(); y <= src.bottom(); y++ )
632 srcList.append( cellAt( x, y ) );
634 TQPtrList<AutoFillSequence> seqList;
635 seqList.setAutoDelete(
true );
636 for ( y = src.top(); y <= src.bottom(); y++ )
637 seqList.append(
new AutoFillSequence( cellAt( x, y ) ) );
638 fillSequence( srcList, destList, seqList );
643 if ( ( src.left() == dest.right() || src.left() == dest.right() - 1) && src.right() >= dest.right() )
645 if ( src.left() != dest.right() )
646 dest.setRight( dest.right() - 1 );
648 for (
int y = dest.top(); y <= dest.bottom(); y++ )
651 TQPtrList<Cell> destList;
653 for ( x = dest.left(); x < src.left(); x++ )
655 destList.append( nonDefaultCell( x, y ) );
657 TQPtrList<Cell> srcList;
658 for ( x = src.left(); x <= src.right(); x++ )
660 srcList.append( cellAt( x, y ) );
662 TQPtrList<AutoFillSequence> seqList;
663 seqList.setAutoDelete(
true );
664 for ( x = src.left(); x <= src.right(); x++ )
665 seqList.append(
new AutoFillSequence( cellAt( x, y ) ) );
666 fillSequence( srcList, destList, seqList,
false );
671 if ( (src.top() == dest.bottom() || src.top() == (dest.bottom() - 1) ) && src.bottom() >= dest.bottom() )
673 if (src.top() != dest.bottom() )
674 dest.setBottom(dest.bottom() - 1);
675 int startVal = TQMIN( dest.left(), src.left());
676 int endVal = TQMAX(src.right(), dest.right());
677 for (
int x = startVal; x <= endVal; x++ )
680 TQPtrList<Cell> destList;
681 for ( y = dest.top(); y < src.top(); y++ )
682 destList.append( nonDefaultCell( x, y ) );
683 TQPtrList<Cell> srcList;
684 for ( y = src.top(); y <= src.bottom(); ++y )
686 srcList.append( cellAt( x, y ) );
688 TQPtrList<AutoFillSequence> seqList;
689 seqList.setAutoDelete(
true );
690 for ( y = src.top(); y <= src.bottom(); y++ )
691 seqList.append(
new AutoFillSequence( cellAt( x, y ) ) );
692 fillSequence( srcList, destList, seqList,
false );
697 enableScrollBarUpdates(
true);
698 checkRangeHBorder(dest.right());
699 checkRangeVBorder(dest.bottom());
701 emit sig_updateView(
this );
706void Sheet::fillSequence( TQPtrList<Cell>& _srcList,
707 TQPtrList<Cell>& _destList,
708 TQPtrList<AutoFillSequence>& _seqList,
711 doc()->emitBeginOperation(
true);
714 if (!FillSequenceWithInterval(_srcList, _destList, _seqList, down))
717 FillSequenceWithCopy(_srcList, _destList, down);
720 doc()->emitEndOperation();
724TQVariant getDiff(
const Value& value1,
const Value& value2 , AutoFillSequenceItem::Type type )
726 if ( type == AutoFillSequenceItem::FLOAT )
728 if ( type == AutoFillSequenceItem::TIME || type == AutoFillSequenceItem::DATE )
731 return TQVariant( (
int)0 );
742bool Sheet::FillSequenceWithInterval(TQPtrList<Cell>& _srcList,
743 TQPtrList<Cell>& _destList,
744 TQPtrList<AutoFillSequence>& _seqList,
747 if (_srcList.first()->isFormula())
750 TQPtrList<AutoFillDeltaSequence> deltaList;
751 deltaList.setAutoDelete(
true );
754 if ( _srcList.first()->value().isNumber() || _srcList.first()->isDate() || _srcList.first()->isTime() )
756 AutoFillSequenceItem::Type type;
758 TQValueVector< TQVariant > tmp( _seqList.count() ); ;
759 TQValueVector< TQVariant > diff( _seqList.count() ); ;
764 Cell * cell = _srcList.first();
765 Cell * cell2 = _srcList.next();
767 bool singleCellOnly = (cell2 == 0);
770 type = AutoFillSequenceItem::DATE;
771 else if ( cell->
isTime() )
772 type = AutoFillSequenceItem::TIME;
774 type = AutoFillSequenceItem::FLOAT;
778 while ( cell && (cell2 || singleCellOnly) )
794 if (type == AutoFillSequenceItem::FLOAT)
795 cell2Value = cellValue;
796 else if ( type == AutoFillSequenceItem::TIME)
797 cell2Value =
Value( cellValue.
asTime().addSecs( 60*60 ) );
798 else if ( type == AutoFillSequenceItem::DATE)
799 cell2Value =
Value ( cellValue.
asDate().addDays( 1 ) );
803 cell2Value = cell2->
value();
807 || ( cell2->
isDate() && type != AutoFillSequenceItem::DATE )
808 || ( cell2->
isTime() && type != AutoFillSequenceItem::TIME ) )
816 TQVariant delta = getDiff(cellValue , cell2Value , type );
821 diff[ count++ ] = delta;
826 if (diff[ p ] == delta)
830 tmp[ tmpcount++ ] = delta;
837 for (
int i = 0; i < tmpcount; ++i )
839 diff[ count++ ] = tmp.at( i );
847 diff[ count++ ] = delta;
853 cell2 = _srcList.next();
857 if (count > 0 && (tmpcount > 0 || count == 1))
859 TQVariant cellValue( (
int) 0 );
867 dest = _destList.first();
868 src = _srcList.last();
872 dest = _destList.last();
873 src = _srcList.first();
878 if ( type == AutoFillSequenceItem::FLOAT )
898 TQVariant currentDiff = diff.at( i );
900 if (cellValue.
type() == TQVariant::Double)
902 cellValue = cellValue.asDouble() + currentDiff.asDouble();
904 cellValue = cellValue.asDouble() - currentDiff.asDouble();
907 cellValue = cellValue.asInt() + currentDiff.asInt();
909 cellValue = cellValue.asInt() - currentDiff.asInt();
911 if ( type == AutoFillSequenceItem::TIME)
914 Value stringValue = doc()->converter()->
asString( timeValue );
917 else if ( type == AutoFillSequenceItem::DATE)
920 Value stringValue = doc()->converter()->
asString( dateValue );
931 dest = _destList.next();
932 src = _srcList.next();
937 dest = _destList.prev();
938 src = _srcList.prev();
942 src = _srcList.last();
969 for (
unsigned int step = 1; step <= _seqList.count() / 2; step++ )
971 kdDebug() <<
"Looking for interval: " << step <<
" seqList count: " << _seqList.count() << endl;
974 if ( _seqList.count() % step == 0 )
985 for (
unsigned int t = 0; t < step; t++ )
987 deltaList.append(
new AutoFillDeltaSequence( _seqList.at(t),
988 _seqList.at(t+step) ) );
989 ok = deltaList.getLast()->isOk();
998 for (
unsigned int tst = 1; ok && ( tst * step < _seqList.count() );
1001 for (
unsigned int s = 0; ok && ( s < step ); s++ )
1003 if ( !_seqList.at( (tst-1) * step + s )->
1004 matches( _seqList.at( tst * step + s ), deltaList.at( s ) ) )
1013 int block = _seqList.count() / step;
1018 cell = _destList.first();
1021 cell = _destList.last();
1022 block -= (_seqList.count() - 1);
1029 kdDebug() <<
"Valid interval, cell: " << cell->
row() <<
" block: " << block << endl;
1049 kdDebug() <<
"Step: " << step <<
" S: " << s <<
" Block " << block
1050 <<
" SeqList: " << _seqList.count()
1051 <<
" SrcList: " << _srcList.count() <<
" DeltaList: " << deltaList.count()
1056 _seqList.at( s )->fillCell( _srcList.at( s ), cell,
1057 deltaList.at( s ), block, down );
1062 cell = _destList.next();
1068 cell = _destList.prev();
1078void Sheet::FillSequenceWithCopy(TQPtrList<Cell>& _srcList,
1079 TQPtrList<Cell>& _destList,
1087 cell = _destList.first();
1089 cell = _destList.last();
1095 s = _srcList.count() - 1;
1097 if ( _srcList.at( s )->value().isNumber() &&
1098 !(_srcList.at( s )->isDate() || _srcList.at( s )->isTime() ) )
1105 if ( s == _srcList.count() )
1110 if ( s >= _srcList.count() )
1111 s = _srcList.count() - 1;
1114 if ( !_srcList.at( s )->text().isEmpty() )
1116 if ( _srcList.at( s )->isFormula() )
1118 TQString d = _srcList.at( s )->encodeFormula();
1121 else if(_srcList.at( s )->value().isNumber() && _srcList.count()==1)
1124 int format_type = _srcList.at( s )->formatType();
1125 if ( format_type == Percentage_format )
1129 else if ( _srcList.at( s )->isTime() )
1137 factor = 0.041666751;
1146 val = (_srcList.at( s )->value().asFloat() - (incr * factor));
1148 val = (_srcList.at( s )->value().asFloat() + (incr * factor));
1151 tmp = tmp.setNum(val);
1155 else if((AutoFillSequenceItem::month != 0L)
1156 && AutoFillSequenceItem::month->find( _srcList.at( s )->text()) != 0L
1157 && AutoFillSequenceItem::month->find( _srcList.at( s )->text()) != AutoFillSequenceItem::month->end()
1158 && _srcList.count() == 1)
1160 TQString strMonth=_srcList.at( s )->text();
1161 int i = AutoFillSequenceItem::month->findIndex( strMonth )+incr;
1162 int k = (i) % AutoFillSequenceItem::month->count();
1163 cell->
setCellText((*AutoFillSequenceItem::month->at( k )));
1166 else if(AutoFillSequenceItem::day != 0L
1167 && AutoFillSequenceItem::day->find( _srcList.at( s )->text()) != 0L
1168 && AutoFillSequenceItem::day->find( _srcList.at( s )->text())
1169 != AutoFillSequenceItem::day->end()
1170 && _srcList.count()==1)
1172 TQString strDay=_srcList.at( s )->text();
1173 int i = AutoFillSequenceItem::day->findIndex( strDay )+incr;
1174 int k = (i) % AutoFillSequenceItem::day->count();
1175 cell->
setCellText((*AutoFillSequenceItem::day->at( k )));
1180 TQRegExp number(
"(\\d+)");
1181 int pos =number.search(_srcList.at( s )->text());
1184 TQString tmp=number.cap(1);
1185 int num=tmp.toInt()+incr;
1186 cell->
setCellText(_srcList.at( s )->text().replace(number,TQString::number(num)));
1189 else if ( !_srcList.at( s )->link().isEmpty() )
1192 cell->
setLink( _srcList.at( s )->link() );
1207 cell = _destList.next();
1212 cell = _destList.prev();
For every cell in the spread sheet there is a Cell object.
TQString encodeFormula(bool _era=false, int _col=-1, int _row=-1) const
encode a formula into a text representation
TQString text() const
Return the text the user entered.
int row() const
Returns the cell's row.
const Value value() const
Returns the value that this cell holds.
void setLink(const TQString &link)
Sets a link for this cell.
bool isFormula() const
Returns true if this cell holds a formula.
void setCellText(const TQString &_text, bool asString=false)
The high-level method for setting text, when the user inputs it.
void copyFormat(const int column, const int row)
Copyies the format from the cell at the position (_column|_row).
bool isDate() const
returns true, if cell format is of date type or content is a date
bool isTime() const
returns true, if cell format is of time type or content is a time
Provides a wrapper for cell value.
bool isNumber() const
Returns true if the type of this value is either integer or floating-point.
TQDate asDate() const
Returns the date representation of this value.
Type type() const
Returns the type of the value.
double asFloat() const
Returns the floating-point value of this value.
long asInteger() const
Returns the integer value of this value.
TQString asString() const
Returns the string value of this value.
TQTime asTime() const
Returns the time representation of this value.