38
38
/** d-pointer of DependencyManager */
39
39
class DependencyList {
41
DependencyList (KSpreadSheet *s);
41
DependencyList (Sheet *s);
42
42
~DependencyList () { reset (); };
43
43
/** clear internal structures */
46
/** handle the fact that a cell has been changed */
47
void cellChanged (const Point &cell);
46
49
/** generate list of dependencies of a cell */
47
void generateDependencies (const KSpreadPoint &cell);
50
void generateDependencies (const Point &cell);
48
51
/** generate list of dependencies of a range */
49
void generateDependencies (const KSpreadRange &range);
52
void generateDependencies (const Range &range);
50
53
/** generate list of dependencies of a range list */
51
54
void generateDependencies (const RangeList &rangeList);
53
56
/** update cells dependending on a given cell */
54
void processDependencies (const KSpreadPoint &cell);
57
void processDependencies (const Point &cell);
55
58
/** update cells dependending on a cell in a given range */
56
void processDependencies (const KSpreadRange &range);
59
void processDependencies (const Range &range);
57
60
/** update cells dependending on a given range-list */
58
61
void processDependencies (const RangeList &rangeList);
60
63
/** get dependencies of a cell */
61
RangeList getDependencies (const KSpreadPoint &cell);
64
RangeList getDependencies (const Point &cell);
62
65
/** get cells depending on this cell, either through normal or range dependency */
63
QValueList<KSpreadPoint> getDependants (const KSpreadPoint &cell);
66
QValueList<Point> getDependants (const Point &cell);
68
void areaModified (const QString &name);
66
70
/** update structures: cell 1 depends on cell 2 */
67
void addDependency (const KSpreadPoint &cell1, const KSpreadPoint &cell2);
71
void addDependency (const Point &cell1, const Point &cell2);
68
72
/** update structures: cell depends on a range */
69
73
void addRangeDependency (const RangeDependency &rd);
70
74
/** remove all dependencies of a cell */
71
void removeDependencies (const KSpreadPoint &cell);
75
void removeDependencies (const Point &cell);
73
77
/** update all cells depending on a range containing this cell */
74
void processRangeDependencies (const KSpreadPoint &cell);
78
void processRangeDependencies (const Point &cell);
76
80
/** update all cells depending on a range intersecting with this range */
77
void processRangeDependencies (const KSpreadRange &range);
81
void processRangeDependencies (const Range &range);
79
83
/** update one cell due to changed dependencies */
80
void updateCell (const KSpreadPoint &cell) const;
84
void updateCell (const Point &cell) const;
82
86
/** return a leading cell for a given cell (used to store range
83
87
dependencies effectively) */
84
KSpreadPoint leadingCell (const KSpreadPoint &cell) const;
88
Point leadingCell (const Point &cell) const;
85
89
/** list of leading cells of all cell chunks that this range belongs to */
86
QValueList<KSpreadPoint> leadingCells (const KSpreadRange &range) const;
90
QValueList<Point> leadingCells (const Range &range) const;
87
91
/** retrieve a list of cells that a given cell depends on */
88
RangeList computeDependencies (const KSpreadPoint &cell) const;
90
/** KSpreadSheet whose dependencies are managed by this instance */
92
RangeList computeDependencies (const Point &cell) const;
94
QValueList<Point> getCellDeps(const Point& cell) const {
95
CellDepsMap::const_iterator it = cellDeps.find( cell );
96
return it == cellDeps.end() ? QValueList<Point>() : *it;
102
/** Sheet whose dependencies are managed by this instance */
93
105
/** dependencies of each cell */
94
QMap<KSpreadPoint, RangeList> dependencies;
106
QMap<Point, RangeList> dependencies;
95
107
/** list of cells (but NOT ranges) that depend on a cell */
96
QMap<KSpreadPoint, QValueList<KSpreadPoint> > cellDeps;
108
typedef QMap<Point, QValueList<Point> > CellDepsMap;
109
CellDepsMap cellDeps;
97
110
/** all range dependencies splitted into cell-chunks (TODO: describe) */
98
QMap<KSpreadPoint, QValueList<RangeDependency> > rangeDeps;
111
QMap<Point, QValueList<RangeDependency> > rangeDeps;
112
/** list of cells referencing a given named area */
113
QMap<QString, QMap<Point, bool> > areaDeps;
116
} // namespace KSpread
103
118
using namespace KSpread;
105
DependencyManager::DependencyManager (KSpreadSheet *s)
120
// This is currently not called - but it's really convenient to call it from
121
// gdb or from debug output to check that everything is set up ok.
122
void DependencyList::dump()
124
QMap<Point, RangeList>::const_iterator it = dependencies.begin();
125
for ( ; it != dependencies.end(); ++it ) {
127
kdDebug() << "Cell " << p.sheetName() << " " << p.pos()
128
<< " depends on :" << endl;
129
RangeList rl = (*it);
130
QValueList<Point>::const_iterator itp = rl.cells.begin();
131
for ( ; itp != rl.cells.end(); ++itp )
132
kdDebug() << " cell " << (*itp).pos() << endl;
133
QValueList<Range>::const_iterator itr = rl.ranges.begin();
134
for ( ; itr != rl.ranges.end(); ++itr )
135
kdDebug() << " range " << (*itr).toString() << endl;
138
CellDepsMap::const_iterator cit = cellDeps.begin();
139
for ( ; cit != cellDeps.end(); ++cit )
142
kdDebug() << "The cells that depend on " << p.sheetName() << " " << p.pos()
144
QValueList<Point>::const_iterator itp = (*cit).begin();
145
for ( ; itp != (*cit).end(); ++itp )
146
kdDebug() << " cell " << (*itp).pos() << endl;
151
DependencyManager::DependencyManager (Sheet *s)
107
153
deps = new DependencyList (s);
121
void DependencyManager::cellChanged (const KSpreadPoint &cell)
167
void DependencyManager::cellChanged (const Point &cell)
123
KSpreadCell *c = cell.cell();
125
// empty or default cell? do nothing
129
//if the cell contains the circle error, we mustn't do anything
130
if (c->testFlag (KSpreadCell::Flag_CircularCalculation))
133
//kdDebug(36001) << "updating dependencies for cell (" <<
134
// c->row() << "," << c->column() << ")" << endl;
136
//don't re-generate dependencies if we're updating dependencies
137
if ( !(c->testFlag (KSpreadCell::Flag_Progress)))
138
deps->generateDependencies (cell);
140
deps->processDependencies (cell);
169
deps->cellChanged (cell);
143
void DependencyManager::rangeChanged (const KSpreadRange &range)
172
void DependencyManager::rangeChanged (const Range &range)
145
174
deps->generateDependencies (range);
146
175
deps->processDependencies (range);
174
208
rangeDeps.clear();
177
RangeList DependencyList::getDependencies (const KSpreadPoint &cell)
211
void DependencyList::cellChanged (const Point &cell)
213
Cell *c = cell.cell();
215
// empty or default cell? do nothing
219
//if the cell contains the circle error, we mustn't do anything
220
if (c->testFlag (Cell::Flag_CircularCalculation))
223
//don't re-generate dependencies if we're updating dependencies
224
if ( !(c->testFlag (Cell::Flag_Progress)))
225
generateDependencies (cell);
227
processDependencies (cell);
230
RangeList DependencyList::getDependencies (const Point &cell)
180
233
//look if the cell has any dependencies
181
234
if (!dependencies.contains (cell))
182
235
return rl; //it doesn't - return an empty list
184
237
//the cell does have dependencies - return them!
185
238
return dependencies[cell];
188
QValueList<KSpreadPoint> DependencyList::getDependants (const KSpreadPoint &cell)
241
QValueList<Point> DependencyList::getDependants (const Point &cell)
190
QValueList<KSpreadPoint> list;
192
243
//cell dependencies go first
193
if (cellDeps.contains (cell))
194
list = cellDeps[cell];
244
QValueList<Point> list = getCellDeps( cell );
196
245
//next, append range dependencies
197
KSpreadPoint leading = leadingCell (cell);
246
Point leading = leadingCell (cell);
198
247
QValueList<RangeDependency>::iterator it;
199
248
if (!rangeDeps.count (leading))
200
249
return list; //no range dependencies in this cell chunk -> nothing more to do
202
251
for (it = rangeDeps[leading].begin();
203
252
it != rangeDeps[leading].end(); ++it)
206
255
//add the depending cell to the list
207
256
if ((*it).range.contains (cell))
210
259
c.setRow ((*it).cellrow);
211
260
c.setColumn ((*it).cellcolumn);
212
c.sheet = (*it).cellsheet;
261
c.setSheet ( (*it).cellsheet );
213
262
list.push_back (c);
220
void DependencyList::addDependency (const KSpreadPoint &cell1,
221
const KSpreadPoint &cell2)
223
//kdDebug(36001) << "Dep. manager: added a dependency" << endl;
269
void DependencyList::areaModified (const QString &name)
271
// since area names are something like aliases, modifying an area name
272
// basically means that all cells referencing this area should be treated
273
// as modified - that will retrieve updated area ranges and also update
274
// everything as necessary ...
275
if (!areaDeps.contains (name))
278
QMap<Point, bool>::iterator it;
279
for (it = areaDeps[name].begin(); it != areaDeps[name].end(); ++it)
281
Cell *c = it.key().cell();
282
// this forces the cell to regenerate everything - new range dependencies
284
c->setValue (c->value ());
288
void DependencyList::addDependency (const Point &cell1,
225
291
//cell2 can be in another sheet (inter-sheet dependency)
226
KSpreadSheet *sh = cell2.sheet;
292
Sheet *sh = cell2.sheet();
234
300
void DependencyList::addRangeDependency (const RangeDependency &rd)
236
302
//target range can be in another sheet (inter-sheet dependency)
237
KSpreadSheet *sh = rd.range.sheet;
303
Sheet *sh = rd.range.sheet();
242
cell.sheet = rd.cellsheet;
308
cell.setSheet (rd.cellsheet);
243
309
cell.setRow (rd.cellrow);
244
310
cell.setColumn (rd.cellcolumn);
245
311
dependencies[cell].ranges.push_back (rd.range);
247
QValueList<KSpreadPoint> leadings = leadingCells (rd.range);
248
QValueList<KSpreadPoint>::iterator it;
313
QValueList<Point> leadings = leadingCells (rd.range);
314
QValueList<Point>::iterator it;
249
315
for (it = leadings.begin(); it != leadings.end(); ++it)
250
316
sh->dependencies()->deps->rangeDeps[*it].push_back (rd);
318
// the target range could be a named area ...
319
if (!rd.range.namedArea().isNull())
320
areaDeps[rd.range.namedArea()][cell] = true;
253
void DependencyList::removeDependencies (const KSpreadPoint &cell)
323
void DependencyList::removeDependencies (const Point &cell)
255
325
//look if the cell has any dependencies
256
326
if (!dependencies.contains (cell))
257
327
return; //it doesn't - nothing more to do
259
329
//first we remove cell-dependencies
260
QValueList<KSpreadPoint> cells = dependencies[cell].cells;
261
QValueList<KSpreadPoint>::iterator it1;
330
QValueList<Point> cells = dependencies[cell].cells;
331
QValueList<Point>::iterator it1;
262
332
for (it1 = cells.begin(); it1 != cells.end(); ++it1)
264
334
//get sheet-pointer - needed to handle inter-sheet dependencies correctly
265
KSpreadSheet *sh = (*it1).sheet;
335
Sheet *sh = (*it1).sheet();
269
339
if (!sh->dependencies()->deps->cellDeps.contains (*it1))
270
340
continue; //this should never happen
272
342
//we no longer depend on this cell
273
QValueList<KSpreadPoint>::iterator cit;
343
QValueList<Point>::iterator cit;
274
344
cit = sh->dependencies()->deps->cellDeps[*it1].find (cell);
275
345
if (cit != sh->dependencies()->deps->cellDeps[*it1].end())
276
346
sh->dependencies()->deps->cellDeps[*it1].erase (cit);
279
349
//then range-dependencies are removed
280
QValueList<KSpreadRange> ranges = dependencies[cell].ranges;
281
QValueList<KSpreadRange>::iterator it2;
282
QValueList<KSpreadPoint> leads;
350
QValueList<Range> ranges = dependencies[cell].ranges;
351
QValueList<Range>::iterator it2;
352
QValueList<Point> leads;
283
353
for (it2 = ranges.begin(); it2 != ranges.end(); ++it2)
285
355
//we construct a list of cell-chunks containing a range and merge it
286
356
//with lists generated from all previous ranges (duplicates are removed)
287
QValueList<KSpreadPoint> leadings = leadingCells (*it2);
357
QValueList<Point> leadings = leadingCells (*it2);
288
358
for (it1 = leadings.begin(); it1 != leadings.end(); ++it1)
289
359
if (!leads.contains (*it1))
290
360
leads.push_back (*it1);
292
362
for (it1 = leads.begin(); it1 != leads.end(); ++it1)
294
364
//get sheet-pointer - needed to handle inter-sheet dependencies correctly
295
KSpreadSheet *sh = (*it1).sheet;
365
Sheet *sh = (*it1).sheet();
299
369
if (sh->dependencies()->deps->rangeDeps.contains (*it1))
301
371
QValueList<RangeDependency>::iterator it3;
302
QValueList<RangeDependency> rdeps =
303
sh->dependencies()->deps->rangeDeps[*it1];
372
it3 = sh->dependencies()->deps->rangeDeps[*it1].begin();
305
373
//erase all range dependencies of this cell in this cell-chunk
306
while (it3 != rdeps.end())
374
while (it3 != sh->dependencies()->deps->rangeDeps[*it1].end())
307
375
if (((*it3).cellrow == cell.row()) &&
308
376
((*it3).cellcolumn == cell.column()))
309
it3 = rdeps.erase (it3);
377
it3 = sh->dependencies()->deps->rangeDeps[*it1].erase (it3);
312
380
//erase the list if we no longer need it
381
if (sh->dependencies()->deps->rangeDeps[*it1].empty())
314
382
sh->dependencies()->deps->rangeDeps.erase (*it1);
318
//finally, remove the entry about this cell
386
// remove information about named area dependencies
387
QMap<QString, QMap<Point, bool> >::iterator itr;
388
for (itr = areaDeps.begin(); itr != areaDeps.end(); ++itr) {
389
if (itr.data().contains (cell))
390
itr.data().remove (cell);
393
// finally, remove the entry about this cell
319
394
dependencies[cell].cells.clear();
320
395
dependencies[cell].ranges.clear();
321
396
dependencies.erase (cell);
324
void DependencyList::generateDependencies (const KSpreadPoint &cell)
399
void DependencyList::generateDependencies (const Point &cell)
326
401
//get rid of old dependencies first
327
402
removeDependencies (cell);
329
404
//new dependencies only need to be generated if the cell contains a formula
330
KSpreadCell *c = sheet->cellAt (cell.column(), cell.row());
405
Cell *c = sheet->cellAt (cell.column(), cell.row());
331
406
if( c->isDefault() )
333
408
if (!c->isFormula())
336
411
//now we need to generate dependencies
337
412
RangeList rl = computeDependencies (cell);
339
414
//now that we have the new dependencies, we put them into our data structures
341
QValueList<KSpreadPoint>::iterator it1;
342
QValueList<KSpreadRange>::iterator it2;
416
QValueList<Point>::iterator it1;
417
QValueList<Range>::iterator it2;
344
419
for (it1 = rl.cells.begin(); it1 != rl.cells.end(); ++it1)
345
420
addDependency (cell, *it1);
346
421
for (it2 = rl.ranges.begin(); it2 != rl.ranges.end(); ++it2)
350
425
rd.cellcolumn = cell.column();
351
426
rd.cellsheet = sheet;
353
if (rd.range.sheet == 0) rd.range.sheet = sheet;
429
if (rd.range.sheet() == 0)
430
rd.range.setSheet(sheet);
354
432
addRangeDependency (rd);
358
void DependencyList::generateDependencies (const KSpreadRange &range)
436
void DependencyList::generateDependencies (const Range &range)
360
438
for (int row = range.startRow(); row <= range.endRow(); row++)
361
439
for (int col = range.startCol(); col <= range.endCol(); col++)
365
443
c.setColumn (col);
367
445
generateDependencies (c);
371
449
void DependencyList::generateDependencies (const RangeList &rangeList)
373
QValueList<KSpreadPoint>::const_iterator it1;
374
QValueList<KSpreadRange>::const_iterator it2;
451
QValueList<Point>::const_iterator it1;
452
QValueList<Range>::const_iterator it2;
376
454
for (it1 = rangeList.cells.begin(); it1 != rangeList.cells.end(); ++it1)
377
455
generateDependencies (*it1);
378
456
for (it2 = rangeList.ranges.begin(); it2 != rangeList.ranges.end(); ++it2)
379
457
generateDependencies (*it2);
382
void DependencyList::processDependencies (const KSpreadPoint &cell)
460
void DependencyList::processDependencies (const Point &cell)
384
if (cellDeps.contains (cell))
386
QValueList<KSpreadPoint> d = cellDeps[cell];
387
QValueList<KSpreadPoint>::iterator it;
388
for (it = d.begin(); it != d.end(); ++it)
462
const QValueList<Point> d = getCellDeps(cell);
463
QValueList<Point>::const_iterator it = d.begin();
464
const QValueList<Point>::const_iterator end = d.end();
465
for (; it != end; ++it)
389
466
updateCell (*it);
392
468
processRangeDependencies (cell);
395
void DependencyList::processRangeDependencies (const KSpreadPoint &cell)
471
void DependencyList::processRangeDependencies (const Point &cell)
397
KSpreadPoint leading = leadingCell (cell);
398
QValueList<RangeDependency>::iterator it;
473
Point leading = leadingCell (cell);
399
474
if (!rangeDeps.count (leading))
400
475
return; //no range dependencies in this cell chunk
402
for (it = rangeDeps[leading].begin();
403
it != rangeDeps[leading].end(); ++it)
477
const QValueList<RangeDependency> rd = rangeDeps[leading];
479
QValueList<RangeDependency>::const_iterator it;
480
for (it = rd.begin(); it != rd.end(); ++it)
405
482
//process all range dependencies, and for each range including the modified cell,
406
483
//recalc the depending cell
407
484
if ((*it).range.contains (cell))
410
487
c.setRow ((*it).cellrow);
411
488
c.setColumn ((*it).cellcolumn);
412
c.sheet = (*it).cellsheet;
489
c.setSheet ( (*it).cellsheet );
418
void DependencyList::processDependencies (const KSpreadRange &range)
495
void DependencyList::processDependencies (const Range &range)
420
497
//each cell's dependencies need to be updated - that cannot be helped - having a range
421
498
//only helps with range dependencies
422
499
for (int row = range.startRow(); row <= range.endRow(); row++)
423
500
for (int col = range.startCol(); col <= range.endCol(); col++)
427
504
c.setColumn (col);
429
if (cellDeps.contains (c))
431
QValueList<KSpreadPoint> d = cellDeps[c];
432
QValueList<KSpreadPoint>::iterator it;
433
for (it = d.begin(); it != d.end(); ++it)
507
const QValueList<Point> d = getCellDeps(c);
508
QValueList<Point>::const_iterator it = d.begin();
509
const QValueList<Point>::const_iterator end = d.end();
510
for (; it != end; ++it)
434
511
updateCell (*it);
438
514
processRangeDependencies (range);
441
void DependencyList::processRangeDependencies (const KSpreadRange &range)
517
void DependencyList::processRangeDependencies (const Range &range)
443
519
//TODO: some optimization, so that we don't recompute cells depending of huge
444
520
//ranges more than once (now we recompute them once per cell-chunk used by their dependency)
445
521
//This will probably happen as a part of splitting this into dep manager
446
522
//and recalc manager
448
QValueList<KSpreadPoint> leadings = leadingCells (range);
449
QValueList<KSpreadPoint>::iterator it;
524
QValueList<Point> leadings = leadingCells (range);
525
QValueList<Point>::iterator it;
450
526
for (it = leadings.begin(); it != leadings.end(); ++it)
452
528
if (!rangeDeps.count (*it))
471
547
void DependencyList::processDependencies (const RangeList &rangeList)
473
QValueList<KSpreadPoint>::const_iterator it1;
474
QValueList<KSpreadRange>::const_iterator it2;
549
QValueList<Point>::const_iterator it1;
550
QValueList<Range>::const_iterator it2;
476
552
for (it1 = rangeList.cells.begin(); it1 != rangeList.cells.end(); ++it1)
477
553
processDependencies (*it1);
478
554
for (it2 = rangeList.ranges.begin(); it2 != rangeList.ranges.end(); ++it2)
479
555
processDependencies (*it2);
482
void DependencyList::updateCell (const KSpreadPoint &cell) const
558
void DependencyList::updateCell (const Point &cell) const
484
KSpreadCell *c = cell.cell();
560
Cell *c = cell.cell();
486
561
//prevent infinite recursion (circular dependencies)
487
if (c->testFlag (KSpreadCell::Flag_Progress))
562
if (c->testFlag (Cell::Flag_Progress) ||
563
c->testFlag (Cell::Flag_CircularCalculation))
489
kdError(36001) << "ERROR: Circle" << endl;
490
c->setFlag(KSpreadCell::Flag_CircularCalculation);
492
v.setError ( "####" );
565
kdError(36001) << "ERROR: Circle, cell " << c->fullName() <<
566
", in dep.manager for sheet " << sheet->name() << endl;
568
// don't set anything if the cell already has all these things set
569
// this prevents endless loop for inter-sheet curcular dependencies,
570
// where the usual mechanisms fail doe to having multiple dependency
572
if (!c->testFlag (Cell::Flag_CircularCalculation))
574
c->setFlag(Cell::Flag_CircularCalculation);
575
v.setError ( "####" );
494
578
//clear the computing-dependencies flag
495
c->clearFlag (KSpreadCell::Flag_Progress);
579
c->clearFlag (Cell::Flag_Progress);
498
//kdDebug() << "Updating depending cell (" <<
499
// c->row() << "," << c->column() << ")" << endl;
500
582
//set the computing-dependencies flag
501
c->setFlag (KSpreadCell::Flag_Progress);
583
c->setFlag (Cell::Flag_Progress);
503
585
//mark the cell as calc-dirty
504
586
c->setCalcDirtyFlag();
506
588
//recalculate the cell
509
591
//clear the computing-dependencies flag
510
c->clearFlag (KSpreadCell::Flag_Progress);
592
c->clearFlag (Cell::Flag_Progress);
513
KSpreadPoint DependencyList::leadingCell (const KSpreadPoint &cell) const
595
Point DependencyList::leadingCell (const Point &cell) const
516
598
c.setRow (cell.row() - cell.row() % CELLCHUNK_ROWS + 1);
517
599
c.setColumn (cell.column() - cell.column() % CELLCHUNK_COLS + 1);
518
c.sheet = cell.sheet;
600
c.setSheet(cell.sheet());
522
QValueList<KSpreadPoint> DependencyList::leadingCells (const KSpreadRange &range) const
604
QValueList<Point> DependencyList::leadingCells (const Range &range) const
524
QValueList<KSpreadPoint> cells;
525
KSpreadPoint cell1, cell2, cell;
606
QValueList<Point> cells;
607
Point cell1, cell2, cell;
527
609
cell1.setRow (range.startRow());
528
610
cell1.setColumn (range.startCol());
529
611
cell2.setRow (range.endRow());
530
612
cell2.setColumn (range.endCol());
531
cell1.sheet = range.sheet;
532
cell2.sheet = range.sheet;
613
cell1.setSheet(range.sheet());
614
cell2.setSheet(range.sheet());
534
616
cell1 = leadingCell (cell1);
535
617
cell2 = leadingCell (cell2);
536
618
for (int row = cell1.row(); row <= cell2.row(); row += CELLCHUNK_ROWS)
540
622
cell.setRow (row);
541
623
cell.setColumn (col);
542
cell.sheet = range.sheet;
624
cell.setSheet(range.sheet());
543
625
cells.push_back (cell);
548
RangeList DependencyList::computeDependencies (const KSpreadPoint &cell) const
630
RangeList DependencyList::computeDependencies (const Point &cell) const
550
KSpreadCell *c = cell.cell();
632
Cell *c = cell.cell();
634
// Not a formula -> no dependencies
551
635
if (!c->isFormula())
552
return RangeList(); //not a formula -> no dependencies
554
QString expr = c->text();
556
//TODO: when the new parser is in use, KSpreadCell will hold a Formula
557
//instance, hence we'll be able to use that one directly
558
Tokens tokens = Formula::scan( expr );
638
// Broken formula -> meaningless dependencies
639
// (tries to avoid c->formula() being null)
643
Formula* f = c->formula();
647
kdDebug() << "Cell at row " << cell.row() << ", col " << cell.column() << " marked as formula, but formula is NULL" << endl;
651
Tokens tokens = f->tokens();
560
653
//return empty list if the tokens aren't valid
561
654
if (!tokens.valid())
562
655
return RangeList();
564
kdDebug(36001) << "Retrieving dependencies for cell with text \"" << expr << "\"" << endl;
567
658
for( unsigned i = 0; i < tokens.count(); i++ )