File indexing completed on 2024-05-12 16:35:10

0001 /* This file is part of the KDE project
0002    Copyright 2006-2007 Stefan Nikolaus <stefan.nikolaus@kdemail.net>
0003    Copyright 2005 Raphael Langerhorst <raphael.langerhorst@kdemail.net>
0004    Copyright 2002-2004 Ariya Hidayat <ariya@kde.org>
0005    Copyright 2002-2003 Norbert Andres <nandres@web.de>
0006    Copyright 2002 John Dailey <dailey@vt.edu>
0007    Copyright 2001-2002 Philipp Mueller <philipp.mueller@gmx.de>
0008    Copyright 2000-2002 Laurent Montel <montel@kde.org>
0009    Copyright 2000-2001 Werner Trobin <trobin@kde.org>
0010    Copyright 1999-2001 David Faure <faure@kde.org>
0011    Copyright 1998-2000 Torben Weis <weis@kde.org>
0012    Copyright 1998-1999 Stephan Kulow <coolo@kde.org>
0013    Copyright 1998 Reginald Stadlbauer <reggie@kde.org>
0014 
0015    This library is free software; you can redistribute it and/or
0016    modify it under the terms of the GNU Library General Public
0017    License as published by the Free Software Foundation; either
0018    version 2 of the License, or (at your option) any later version.
0019 
0020    This library is distributed in the hope that it will be useful,
0021    but WITHOUT ANY WARRANTY; without even the implied warranty of
0022    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0023    Library General Public License for more details.
0024 
0025    You should have received a copy of the GNU Library General Public License
0026    along with this library; see the file COPYING.LIB.  If not, write to
0027    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0028    Boston, MA 02110-1301, USA.
0029 */
0030 
0031 #include "AutoFillCommand.h"
0032 
0033 #include "Localization.h"
0034 #include "Map.h"
0035 #include "Sheet.h"
0036 #include "Value.h"
0037 #include "ValueConverter.h"
0038 #include "SheetsDebug.h"
0039 
0040 #include <KSharedConfig>
0041 #include <kconfig.h>
0042 #include <kconfiggroup.h>
0043 
0044 #include <QList>
0045 #include <QRegExp>
0046 
0047 #include <math.h>
0048 
0049 using namespace Calligra::Sheets;
0050 
0051 QStringList *AutoFillCommand::month = 0;
0052 QStringList *AutoFillCommand::shortMonth = 0;
0053 QStringList *AutoFillCommand::day = 0;
0054 QStringList *AutoFillCommand::shortDay = 0;
0055 QStringList *AutoFillCommand::other = 0;
0056 
0057 /**********************************************************************************
0058  *
0059  * AutoFillSequenceItem
0060  *
0061  **********************************************************************************/
0062 
0063 namespace Calligra
0064 {
0065 namespace Sheets
0066 {
0067 /**
0068  * A cell content for auto-filling.
0069  */
0070 class AutoFillSequenceItem
0071 {
0072 public:
0073     enum Type { VALUE, FORMULA, DAY, SHORTDAY, MONTH, SHORTMONTH, OTHER };
0074 
0075     explicit AutoFillSequenceItem(const Cell& cell);
0076 
0077     Value delta(AutoFillSequenceItem *_seq, bool *ok) const;
0078 
0079     Value nextValue(int _no, Value _delta) const;
0080     Value prevValue(int _no, Value _delta) const;
0081 
0082     Type type() const {
0083         return m_type;
0084     }
0085     Value value() const {
0086         return m_value;
0087     }
0088     int otherEnd() const {
0089         return m_otherEnd;
0090     }
0091     int otherBegin() const {
0092         return m_otherBegin;
0093     }
0094 
0095 protected:
0096     Value   m_value;
0097     Type    m_type;
0098     int     m_otherBegin;
0099     int     m_otherEnd;
0100 };
0101 
0102 } // namespace Sheets
0103 } // namespace Calligra
0104 
0105 
0106 AutoFillSequenceItem::AutoFillSequenceItem(const Cell& cell)
0107         : m_value()
0108         , m_type(VALUE)
0109         , m_otherBegin(0)
0110         , m_otherEnd(0)
0111 {
0112     if (cell.isFormula()) {
0113         m_value = Value(cell.encodeFormula());
0114         m_type = FORMULA;
0115     } else if (cell.isDate()) {
0116         m_value = cell.sheet()->map()->converter()->asDate(cell.value());
0117         m_type = VALUE;
0118     } else if (cell.isTime() || cell.value().format() == Value::fmt_DateTime) {
0119         m_value = cell.sheet()->map()->converter()->asDateTime(cell.value());
0120         m_type = VALUE;
0121     } else if (cell.value().isNumber()) {
0122         m_value = cell.value();
0123         m_type = VALUE;
0124     } else {
0125         m_value = cell.value();
0126         m_type = VALUE;
0127 
0128         if (AutoFillCommand::month == 0) {
0129             AutoFillCommand::month = new QStringList();
0130             AutoFillCommand::month->append(i18n("January"));
0131             AutoFillCommand::month->append(i18n("February"));
0132             AutoFillCommand::month->append(i18n("March"));
0133             AutoFillCommand::month->append(i18n("April"));
0134             AutoFillCommand::month->append(i18n("May"));
0135             AutoFillCommand::month->append(i18n("June"));
0136             AutoFillCommand::month->append(i18n("July"));
0137             AutoFillCommand::month->append(i18n("August"));
0138             AutoFillCommand::month->append(i18n("September"));
0139             AutoFillCommand::month->append(i18n("October"));
0140             AutoFillCommand::month->append(i18n("November"));
0141             AutoFillCommand::month->append(i18n("December"));
0142         }
0143 
0144         if (AutoFillCommand::shortMonth == 0) {
0145             AutoFillCommand::shortMonth = new QStringList();
0146             AutoFillCommand::shortMonth->append(i18n("Jan"));
0147             AutoFillCommand::shortMonth->append(i18n("Feb"));
0148             AutoFillCommand::shortMonth->append(i18n("Mar"));
0149             AutoFillCommand::shortMonth->append(i18n("Apr"));
0150             AutoFillCommand::shortMonth->append(i18nc("May short", "May"));
0151             AutoFillCommand::shortMonth->append(i18n("Jun"));
0152             AutoFillCommand::shortMonth->append(i18n("Jul"));
0153             AutoFillCommand::shortMonth->append(i18n("Aug"));
0154             AutoFillCommand::shortMonth->append(i18n("Sep"));
0155             AutoFillCommand::shortMonth->append(i18n("Oct"));
0156             AutoFillCommand::shortMonth->append(i18n("Nov"));
0157             AutoFillCommand::shortMonth->append(i18n("Dec"));
0158         }
0159 
0160         if (AutoFillCommand::day == 0) {
0161             AutoFillCommand::day = new QStringList();
0162             AutoFillCommand::day->append(i18n("Monday"));
0163             AutoFillCommand::day->append(i18n("Tuesday"));
0164             AutoFillCommand::day->append(i18n("Wednesday"));
0165             AutoFillCommand::day->append(i18n("Thursday"));
0166             AutoFillCommand::day->append(i18n("Friday"));
0167             AutoFillCommand::day->append(i18n("Saturday"));
0168             AutoFillCommand::day->append(i18n("Sunday"));
0169         }
0170 
0171         if (AutoFillCommand::shortDay == 0) {
0172             AutoFillCommand::shortDay = new QStringList();
0173             AutoFillCommand::shortDay->append(i18n("Mon"));
0174             AutoFillCommand::shortDay->append(i18n("Tue"));
0175             AutoFillCommand::shortDay->append(i18n("Wed"));
0176             AutoFillCommand::shortDay->append(i18n("Thu"));
0177             AutoFillCommand::shortDay->append(i18n("Fri"));
0178             AutoFillCommand::shortDay->append(i18n("Sat"));
0179             AutoFillCommand::shortDay->append(i18n("Sun"));
0180         }
0181 
0182         if (AutoFillCommand::other == 0) {
0183             // AutoFillCommand::other = new QStringList();
0184             KSharedConfigPtr config = KSharedConfig::openConfig();
0185             AutoFillCommand::other = new QStringList(config->group("Parameters").readEntry("Other list", QStringList()));
0186         }
0187 
0188         if (AutoFillCommand::month->contains(m_value.asString())) {
0189             m_type = MONTH;
0190             return;
0191         }
0192 
0193         if (AutoFillCommand::shortMonth->contains(m_value.asString())) {
0194             m_type = SHORTMONTH;
0195             return;
0196         }
0197 
0198         if (AutoFillCommand::day->contains(m_value.asString())) {
0199             m_type = DAY;
0200             return;
0201         }
0202 
0203         if (AutoFillCommand::shortDay->contains(m_value.asString())) {
0204             m_type = SHORTDAY;
0205             return;
0206         }
0207 
0208         if (AutoFillCommand::other->contains(m_value.asString())) {
0209             m_type = OTHER;
0210             int index = AutoFillCommand::other->indexOf(m_value.asString());
0211             int otherBegin = AutoFillCommand::other->lastIndexOf("\\", index); // backward
0212             int otherEnd = AutoFillCommand::other->indexOf("\\", index); // forward
0213             m_otherBegin = (otherBegin != -1) ? otherBegin : 0;
0214             m_otherEnd = (otherEnd != -1) ? otherEnd : AutoFillCommand::other->count();
0215             return;
0216         }
0217     }
0218 }
0219 
0220 Value AutoFillSequenceItem::delta(AutoFillSequenceItem *seq, bool *ok) const
0221 {
0222     if (seq->type() != m_type) {
0223         *ok = false;
0224         return Value();
0225     }
0226 
0227     *ok = true;
0228 
0229     switch (m_type) {
0230     case VALUE:
0231     case FORMULA: {
0232         switch (m_value.type()) {
0233         case Value::Boolean: {
0234             // delta indicates a flipping of the boolean
0235             if (seq->value().type() != Value::Boolean)
0236                 *ok = false;
0237             return Value(seq->value().asBoolean() != m_value.asBoolean());
0238         }
0239         case Value::Integer: {
0240             if (seq->value().type() == Value::Empty)
0241                 *ok = false;
0242             Value value(seq->value().asInteger() - m_value.asInteger());
0243             value.setFormat(m_value.format()); // may be a date format
0244             return value;
0245         }
0246         case Value::Float: {
0247             if (seq->value().type() == Value::Empty)
0248                 *ok = false;
0249             Value value(seq->value().asFloat() - m_value.asFloat());
0250             value.setFormat(m_value.format()); // may be a time format
0251             return value;
0252         }
0253         case Value::Complex: {
0254             if (seq->value().type() == Value::Empty)
0255                 *ok = false;
0256             return Value(seq->value().asComplex() - m_value.asComplex());
0257         }
0258         case Value::Empty:
0259         case Value::String:
0260         case Value::Array:
0261         case Value::CellRange:
0262         case Value::Error: {
0263             *ok = (m_value == seq->value());
0264             return Value();
0265         }
0266         }
0267     }
0268     case MONTH: {
0269         const int i = AutoFillCommand::month->indexOf(m_value.asString());
0270         const int j = AutoFillCommand::month->indexOf(seq->value().asString());
0271         return Value(j - i);
0272     }
0273     case SHORTMONTH: {
0274         const int i = AutoFillCommand::shortMonth->indexOf(m_value.asString());
0275         const int j = AutoFillCommand::shortMonth->indexOf(seq->value().asString());
0276         return Value(j - i);
0277     }
0278     case DAY: {
0279         const int i = AutoFillCommand::day->indexOf(m_value.asString());
0280         const int j = AutoFillCommand::day->indexOf(seq->value().asString());
0281         return Value(j - i);
0282     }
0283     case SHORTDAY: {
0284         const int i = AutoFillCommand::shortDay->indexOf(m_value.asString());
0285         const int j = AutoFillCommand::shortDay->indexOf(seq->value().asString());
0286         return Value(j - i);
0287     }
0288     case OTHER: {
0289         *ok = (m_otherEnd != seq->otherEnd() || m_otherBegin != seq->otherBegin());
0290         const int i = AutoFillCommand::other->indexOf(m_value.asString());
0291         const int j = AutoFillCommand::other->indexOf(seq->value().asString());
0292         int k = j;
0293         if (j < i)
0294             k += (m_otherEnd - m_otherBegin - 1);
0295         /*        if (j + 1 == i)
0296                     return -1.0;
0297                 else*/
0298         return Value(k - i);
0299     }
0300     default:
0301         *ok = false;
0302     }
0303     return Value();
0304 }
0305 
0306 Value AutoFillSequenceItem::nextValue(int _no, Value _delta) const
0307 {
0308     switch (m_type) {
0309     case VALUE:
0310     case FORMULA: {
0311         if (m_value.isBoolean()) {
0312             if (!_delta.asBoolean() || _delta.isEmpty()) // no change?
0313                 return m_value;
0314             return Value((_no % 2) ? !m_value.asBoolean() : m_value.asBoolean());
0315         } else if (m_value.isInteger()) {
0316             Value value(m_value.asInteger() + _no * _delta.asInteger());
0317             value.setFormat(_delta.format());
0318             return value;
0319         } else if (m_value.isFloat()) {
0320             Value value(m_value.asFloat() + (long double)_no * _delta.asFloat());
0321             value.setFormat(_delta.format());
0322             return value;
0323         } else if (m_value.isComplex()) {
0324             Value value(m_value.asComplex() + (long double)_no * _delta.asComplex());
0325             value.setFormat(_delta.format());
0326             return value;
0327         } else // string or empty
0328             return m_value;
0329     }
0330     case MONTH: {
0331         int i = AutoFillCommand::month->indexOf(m_value.asString());
0332         int j = i + _no * _delta.asInteger();
0333         while (j < 0)
0334             j += AutoFillCommand::month->count();
0335         int k = j % AutoFillCommand::month->count();
0336         return Value(AutoFillCommand::month->at(k));
0337     }
0338     case SHORTMONTH: {
0339         int i = AutoFillCommand::shortMonth->indexOf(m_value.asString());
0340         int j = i + _no * _delta.asInteger();
0341         while (j < 0)
0342             j += AutoFillCommand::shortMonth->count();
0343         int k = j % AutoFillCommand::shortMonth->count();
0344         return Value(AutoFillCommand::shortMonth->at(k));
0345     }
0346     case DAY: {
0347         int i = AutoFillCommand::day->indexOf(m_value.asString());
0348         int j = i + _no * _delta.asInteger();
0349         while (j < 0)
0350             j += AutoFillCommand::day->count();
0351         int k = j % AutoFillCommand::day->count();
0352         return Value(AutoFillCommand::day->at(k));
0353     }
0354     case SHORTDAY: {
0355         int i = AutoFillCommand::shortDay->indexOf(m_value.asString());
0356         int j = i + _no * _delta.asInteger();
0357         while (j < 0)
0358             j += AutoFillCommand::shortDay->count();
0359         int k = j % AutoFillCommand::shortDay->count();
0360         return Value(AutoFillCommand::shortDay->at(k));
0361     }
0362     case OTHER: {
0363         int i = AutoFillCommand::other->indexOf(m_value.asString()) - (m_otherBegin + 1);
0364         int j = i + _no * _delta.asInteger();
0365         int k = j % (m_otherEnd - m_otherBegin - 1);
0366         return Value(AutoFillCommand::other->at((k + m_otherBegin + 1)));
0367     }
0368     default:
0369         break;
0370     }
0371     return Value();
0372 }
0373 
0374 Value AutoFillSequenceItem::prevValue(int _no, Value _delta) const
0375 {
0376     switch (m_type) {
0377     case VALUE:
0378     case FORMULA: {
0379         if (m_value.isBoolean()) {
0380             if (!_delta.asBoolean() || _delta.isEmpty()) // no change?
0381                 return m_value;
0382             return Value((_no % 2) ? !m_value.asBoolean() : m_value.asBoolean());
0383         } else if (m_value.isInteger()) {
0384             Value value(m_value.asInteger() - _no * _delta.asInteger());
0385             value.setFormat(_delta.format());
0386             return value;
0387         } else if (m_value.isFloat()) {
0388             Value value(m_value.asFloat() - (long double)_no * _delta.asFloat());
0389             value.setFormat(_delta.format());
0390             return value;
0391         } else if (m_value.isComplex()) {
0392             Value value(m_value.asComplex() - (long double)_no * _delta.asComplex());
0393             value.setFormat(_delta.format());
0394             return value;
0395         } else // string or empty
0396             return m_value;
0397     }
0398     case MONTH: {
0399         int i = AutoFillCommand::month->indexOf(m_value.asString());
0400         int j = i - _no * _delta.asInteger();
0401         while (j < 0)
0402             j += AutoFillCommand::month->count();
0403         int k = j % AutoFillCommand::month->count();
0404         return Value(AutoFillCommand::month->at(k));
0405     }
0406     case SHORTMONTH: {
0407         int i = AutoFillCommand::shortMonth->indexOf(m_value.asString());
0408         int j = i - _no * _delta.asInteger();
0409         while (j < 0)
0410             j += AutoFillCommand::shortMonth->count();
0411         int k = j % AutoFillCommand::shortMonth->count();
0412         return Value(AutoFillCommand::shortMonth->at(k));
0413     }
0414     case DAY: {
0415         int i = AutoFillCommand::day->indexOf(m_value.asString());
0416         int j = i - _no * _delta.asInteger();
0417         while (j < 0)
0418             j += AutoFillCommand::day->count();
0419         int k = j % AutoFillCommand::day->count();
0420         return Value(AutoFillCommand::day->at(k));
0421     }
0422     case SHORTDAY: {
0423         int i = AutoFillCommand::shortDay->indexOf(m_value.asString());
0424         int j = i - _no * _delta.asInteger();
0425         while (j < 0)
0426             j += AutoFillCommand::shortDay->count();
0427         int k = j % AutoFillCommand::shortDay->count();
0428         return Value(AutoFillCommand::shortDay->at(k));
0429     }
0430     case OTHER: {
0431         int i = AutoFillCommand::other->indexOf(m_value.asString()) - (m_otherBegin + 1);
0432         int j = i - _no * _delta.asInteger();
0433         while (j < 0)
0434             j += (m_otherEnd - m_otherBegin - 1);
0435         int k = j % (m_otherEnd - m_otherBegin - 1);
0436         return Value(AutoFillCommand::other->at((k + m_otherBegin + 1)));
0437     }
0438     default:
0439         break;
0440     }
0441     return Value();
0442 }
0443 
0444 
0445 /**********************************************************************************
0446  *
0447  * AutoFillSequence
0448  *
0449  **********************************************************************************/
0450 
0451 namespace Calligra
0452 {
0453 namespace Sheets
0454 {
0455 /**
0456  * A sequence of cell contents for auto-filling.
0457  */
0458 class AutoFillSequence : public QList<AutoFillSequenceItem*>
0459 {
0460 public:
0461     AutoFillSequence();
0462     AutoFillSequence(const QList<AutoFillSequenceItem*>&);
0463     ~AutoFillSequence();
0464 
0465     QList<Value> createDeltaSequence(int intervalLength) const;
0466 };
0467 
0468 } // namespace Sheets
0469 } // namespace Calligra
0470 
0471 AutoFillSequence::AutoFillSequence()
0472 {
0473 }
0474 
0475 AutoFillSequence::AutoFillSequence(const QList<AutoFillSequenceItem*>& list)
0476         : QList<AutoFillSequenceItem*>(list)
0477 {
0478 }
0479 
0480 AutoFillSequence::~AutoFillSequence()
0481 {
0482 }
0483 
0484 QList<Value> AutoFillSequence::createDeltaSequence(int intervalLength) const
0485 {
0486     bool ok = true;
0487     QList<Value> deltaSequence;
0488 
0489     // Guess the delta by looking at cells 0...2*intervalLength-1
0490     //
0491     // Since the interval may be of length 'intervalLength' we calculate the delta
0492     // between cells 0 and intervalLength, 1 and intervalLength+1, ...., intervalLength-1 and 2*intervalLength-1.
0493     for (int t = 0; t < intervalLength /*&& t + intervalLength < count()*/; ++t) {
0494         deltaSequence.append(value(t)->delta(value((t + intervalLength) % count()), &ok));
0495         if (!ok)
0496             return QList<Value>();
0497     }
0498 
0499     // fill to the interval length
0500     while (deltaSequence.count() < intervalLength)
0501         deltaSequence.append(Value());
0502 
0503     return deltaSequence;
0504 }
0505 
0506 
0507 /**********************************************************************************
0508  *
0509  * File static helper functions
0510  *
0511  **********************************************************************************/
0512 
0513 static QList<Value> findInterval(const AutoFillSequence& _seqList)
0514 {
0515     // What is the interval (block)? If your sheet looks like this:
0516     // 1 3 5 7 9
0517     // then the interval has the length 1 and the delta list is [2].
0518     // 2 200 3 300 4 400
0519     // Here the interval has length 2 and the delta list is [1,100]
0520 
0521     QList<Value> deltaSequence;
0522 
0523     debugSheets << "Sequence length:" << _seqList.count();
0524 
0525     // How big is the interval. It is in the range from [1...n].
0526     //
0527     // We try to find the shortest interval.
0528     int intervalLength = 1;
0529     for (intervalLength = 1; intervalLength < _seqList.count(); ++intervalLength) {
0530         debugSheets << "Checking interval of length:" << intervalLength;
0531 
0532         // Create the delta list.
0533         deltaSequence = _seqList.createDeltaSequence(intervalLength);
0534 
0535         QString str("Deltas: [ ");
0536         foreach(const Value &v, deltaSequence) {
0537             if (v.isBoolean())
0538                 str += v.asBoolean() ? "change " : "nochange ";
0539             else if (v.isInteger())
0540                 str += QString::number(v.asInteger()) + ' ';
0541             else if (v.isFloat())
0542                 str += QString::number((double) v.asFloat()) + ' ';
0543             else
0544                 str += v.asString() + ' ';
0545         }
0546         str += ']';
0547         debugSheets << str;
0548 
0549         // Verify the delta by looking at cells intervalLength.._seqList.count().
0550         // We only looked at the cells 0..2*intervalLength-1.
0551         // Now test whether the cells from "(i-1) * intervalLength + s" share the same delta
0552         // with the cell "i * intervalLength + s" for all test=1..._seqList.count()/intervalLength
0553         // and for all s=0...intervalLength-1.
0554         for (int i = 1; (i + 1) * intervalLength < _seqList.count(); ++i) {
0555             AutoFillSequence tail = _seqList.mid(i * intervalLength);
0556 //             debugSheets <<"Verifying for sequence after" << i * intervalLength <<", length:" << tail.count();
0557             QList<Value> otherDeltaSequence = tail.createDeltaSequence(intervalLength);
0558             if (deltaSequence != otherDeltaSequence) {
0559                 debugSheets << "Interval does not match.";
0560                 deltaSequence.clear();
0561                 break;
0562             }
0563         }
0564 
0565         // Did we find a valid interval?
0566         if (!deltaSequence.isEmpty())
0567             break;
0568     }
0569 
0570     // if the full interval has to be taken fill the delta sequence with zeros
0571     if (intervalLength == _seqList.count()) {
0572         while (intervalLength--)
0573             deltaSequence.append(Value());
0574 
0575         QString str("Deltas: [ ");
0576         foreach(const Value &v, deltaSequence) {
0577             if (v.isBoolean())
0578                 str += v.asBoolean() ? "change " : "nochange ";
0579             else if (v.isInteger())
0580                 str += QString::number(v.asInteger()) + ' ';
0581             else if (v.isFloat())
0582                 str += QString::number((double) v.asFloat()) + ' ';
0583             else
0584                 str += v.asString() + ' ';
0585         }
0586         str += ']';
0587         debugSheets << str;
0588     }
0589 
0590     return deltaSequence;
0591 }
0592 
0593 static void fillSequence(const QList<Cell>& _srcList,
0594                          const QList<Cell>& _destList,
0595                          const AutoFillSequence& _seqList,
0596                          const QList<Value>& deltaSequence,
0597                          bool down)
0598 {
0599     const int intervalLength = deltaSequence.count();
0600     // starting position depends on the sequence and interval length
0601     int s = _srcList.count() % intervalLength;
0602     // Amount of intervals (blocks)
0603     int block = _srcList.count() / intervalLength;
0604     debugSheets << "Valid interval, number of intervals:" << block;
0605 
0606     // Start iterating with the first cell
0607     Cell cell;
0608     int destIndex = 0;
0609     if (down)
0610         cell = _destList.first();
0611     else {
0612         cell = _destList.last();
0613         destIndex = _destList.count() - 1;
0614         block -= (_srcList.count() - 1);
0615     }
0616 
0617     // Fill destination cells
0618     //
0619     while (!cell.isNull()) {
0620         // End of block? -> start again from beginning
0621         if (down) {
0622             if (s == intervalLength) {
0623                 ++block;
0624                 s = 0;
0625             }
0626         } else {
0627             if (s == -1) {
0628                 s = intervalLength - 1;
0629                 ++block;
0630             }
0631         }
0632 
0633         debugSheets << "Cell:" << cell.name() << ", position:" << s << ", block:" << block;
0634 
0635         // Calculate the new value of 'cell' by adding 'block' times the delta to the
0636         // value of cell 's'.
0637         //
0638         Value value;
0639         if (down)
0640             value = _seqList.value(s)->nextValue(block, deltaSequence.value(s));
0641         else
0642             value = _seqList.value(s)->prevValue(block, deltaSequence.value(s));
0643 
0644         // insert the new value
0645         //
0646         if (_seqList.value(s)->type() == AutoFillSequenceItem::FORMULA) {
0647             // Special handling for formulas
0648             cell.parseUserInput(cell.decodeFormula(_seqList.value(s)->value().asString()));
0649         } else if (value.format() == Value::fmt_Time) {
0650             const Value timeValue = cell.sheet()->map()->converter()->asTime(value);
0651             cell.setValue(timeValue);
0652             cell.setUserInput(cell.sheet()->map()->converter()->asString(timeValue).asString());
0653         } else if (value.format() == Value::fmt_Date) {
0654             const Value dateValue = cell.sheet()->map()->converter()->asDate(value);
0655             cell.setValue(dateValue);
0656             cell.setUserInput(cell.sheet()->map()->converter()->asString(dateValue).asString());
0657         } else if (value.type() == Value::Boolean ||
0658                    value.type() == Value::Complex ||
0659                    value.type() == Value::Float ||
0660                    value.type() == Value::Integer) {
0661             cell.setValue(value);
0662             cell.setUserInput(cell.sheet()->map()->converter()->asString(value).asString());
0663         } else { // if (value.type() == Value::String)
0664             QRegExp number("(\\d+)");
0665             int pos = number.indexIn(value.asString());
0666             if (pos != -1) {
0667                 const int num = number.cap(1).toInt() + 1;
0668                 cell.parseUserInput(value.asString().replace(number, QString::number(num)));
0669             } else if (!_srcList.at(s).link().isEmpty()) {
0670                 cell.parseUserInput(value.asString());
0671                 cell.setLink(_srcList.at(s).link());
0672             } else {
0673                 cell.setValue(value);
0674                 cell.setUserInput(value.asString());
0675             }
0676         }
0677 
0678         // copy the style of the source cell
0679         //
0680         cell.copyFormat(_srcList.at(s));
0681 
0682         // next/previous cell
0683         if (down) {
0684             cell = _destList.value(++destIndex);
0685             ++s;
0686         } else {
0687             cell = _destList.value(--destIndex);
0688             --s;
0689         }
0690     }
0691 }
0692 
0693 
0694 /**********************************************************************************
0695  *
0696  * AutoFillCommand
0697  *
0698  **********************************************************************************/
0699 
0700 AutoFillCommand::AutoFillCommand()
0701 {
0702     setText(kundo2_i18n("Autofill"));
0703 }
0704 
0705 AutoFillCommand::~AutoFillCommand()
0706 {
0707 }
0708 
0709 void AutoFillCommand::setSourceRange(const QRect& range)
0710 {
0711     m_sourceRange = range;
0712 }
0713 
0714 void AutoFillCommand::setTargetRange(const QRect& range)
0715 {
0716     m_targetRange = range;
0717 }
0718 
0719 bool AutoFillCommand::mainProcessing()
0720 {
0721     if (m_sourceRange.contains(m_targetRange))
0722         return false;
0723 
0724     if (m_reverse) {
0725         // reverse - use the stored value
0726         AbstractDataManipulator::mainProcessing();
0727         return true;
0728     }
0729 
0730     // Fill from left to right
0731     if (m_sourceRange.left() == m_targetRange.left() && m_sourceRange.right() < m_targetRange.right()) {
0732         for (int y = m_sourceRange.top(); y <= m_sourceRange.bottom(); ++y) {
0733             int x;
0734             QList<Cell> destList;
0735             for (x = m_sourceRange.right() + 1; x <= m_targetRange.right(); ++x)
0736                 destList.append(Cell(m_sheet, x, y));
0737             QList<Cell> srcList;
0738             for (x = m_sourceRange.left(); x <= m_sourceRange.right(); ++x)
0739                 srcList.append(Cell(m_sheet, x, y));
0740             AutoFillSequence seqList;
0741             for (x = m_sourceRange.left(); x <= m_sourceRange.right(); ++x)
0742                 seqList.append(new AutoFillSequenceItem(Cell(m_sheet, x, y)));
0743             fillSequence(srcList, destList, seqList);
0744             qDeleteAll(seqList);
0745         }
0746     }
0747 
0748     // Fill from top to bottom
0749     if (m_sourceRange.top() == m_targetRange.top() && m_sourceRange.bottom() < m_targetRange.bottom()) {
0750         for (int x = m_sourceRange.left(); x <= m_targetRange.right(); ++x) {
0751             int y;
0752             QList<Cell> destList;
0753             for (y = m_sourceRange.bottom() + 1; y <= m_targetRange.bottom(); ++y)
0754                 destList.append(Cell(m_sheet, x, y));
0755             QList<Cell> srcList;
0756             for (y = m_sourceRange.top(); y <= m_sourceRange.bottom(); ++y)
0757                 srcList.append(Cell(m_sheet, x, y));
0758             AutoFillSequence seqList;
0759             for (y = m_sourceRange.top(); y <= m_sourceRange.bottom(); ++y)
0760                 seqList.append(new AutoFillSequenceItem(Cell(m_sheet, x, y)));
0761             fillSequence(srcList, destList, seqList);
0762             qDeleteAll(seqList);
0763         }
0764     }
0765 
0766     // Fill from right to left
0767     if (m_sourceRange.left() == m_targetRange.right() && m_sourceRange.right() >= m_targetRange.right()) {
0768         for (int y = m_targetRange.top(); y <= m_targetRange.bottom(); ++y) {
0769             int x;
0770             QList<Cell> destList;
0771             for (x = m_targetRange.left(); x < m_sourceRange.left(); ++x)
0772                 destList.append(Cell(m_sheet, x, y));
0773             QList<Cell> srcList;
0774             for (x = m_sourceRange.left(); x <= m_sourceRange.right(); ++x)
0775                 srcList.append(Cell(m_sheet, x, y));
0776             AutoFillSequence seqList;
0777             for (x = m_sourceRange.left(); x <= m_sourceRange.right(); ++x)
0778                 seqList.append(new AutoFillSequenceItem(Cell(m_sheet, x, y)));
0779             fillSequence(srcList, destList, seqList, false);
0780             qDeleteAll(seqList);
0781         }
0782     }
0783 
0784     // Fill from bottom to top
0785     if (m_sourceRange.top() == m_targetRange.bottom() && m_sourceRange.bottom() >= m_targetRange.bottom()) {
0786         const int startVal = qMin(m_targetRange.left(), m_sourceRange.left());
0787         const int endVal = qMax(m_sourceRange.right(), m_targetRange.right());
0788         for (int x = startVal; x <= endVal; ++x) {
0789             int y;
0790             QList<Cell> destList;
0791             for (y = m_targetRange.top(); y < m_sourceRange.top(); ++y)
0792                 destList.append(Cell(m_sheet, x, y));
0793             QList<Cell> srcList;
0794             for (y = m_sourceRange.top(); y <= m_sourceRange.bottom(); ++y)
0795                 srcList.append(Cell(m_sheet, x, y));
0796             AutoFillSequence seqList;
0797             for (y = m_sourceRange.top(); y <= m_sourceRange.bottom(); ++y)
0798                 seqList.append(new AutoFillSequenceItem(Cell(m_sheet, x, y)));
0799             fillSequence(srcList, destList, seqList, false);
0800             qDeleteAll(seqList);
0801         }
0802     }
0803     return true;
0804 }
0805 
0806 void AutoFillCommand::fillSequence(const QList<Cell>& _srcList,
0807                                    const QList<Cell>& _destList,
0808                                    const AutoFillSequence& _seqList,
0809                                    bool down)
0810 {
0811     if (_srcList.isEmpty() || _destList.isEmpty())
0812         return;
0813 
0814     // find an interval to use to fill the sequence
0815     QList<Value> deltaSequence;
0816 
0817     //If we only have a single cell, the interval will depend upon the data type.
0818     //- For numeric values, set the interval to 0 as we don't know what might be useful as a sequence
0819     //- For time values, set the interval to one hour, as this will probably be the most useful setting
0820     //- For date values, set the interval to one day, as this will probably be the most useful setting
0821     //
0822     //Note that the above options were chosen for consistency with Excel.  Gnumeric (1.59) sets
0823     //the interval to 0 for all types, OpenOffice.org (2.00) uses increments of 1.00, 1 hour and 1 day
0824     //respectively
0825     if (_srcList.count() == 1) {
0826         const Cell cell = _srcList.value(0);
0827         if (cell.isTime() || cell.value().format() == Value::fmt_DateTime) {
0828             // TODO Stefan: delta depending on minimum unit of format
0829             deltaSequence.append(Value(QTime(1, 0)));
0830         } else if (cell.isDate()) {
0831             // TODO Stefan: delta depending on minimum unit of format
0832             Value value(1);
0833             value.setFormat(Value::fmt_Date);
0834             deltaSequence.append(value);
0835         } else
0836             deltaSequence.append(Value());
0837     } else
0838         deltaSequence = findInterval(_seqList);
0839 
0840     // fill the sequence
0841     ::fillSequence(_srcList, _destList, _seqList, deltaSequence, down);
0842 }