summaryrefslogtreecommitdiff
path: root/noncore/apps/opie-sheet/sheet.cpp
authorthufir <thufir>2002-07-04 16:58:16 (UTC)
committer thufir <thufir>2002-07-04 16:58:16 (UTC)
commitd2b982a38091cbc7cd4eba0994ab6c5e3c7f7189 (patch) (unidiff)
treed1e0a5fa80a12717b46257936ee3f8bb1b3ef89e /noncore/apps/opie-sheet/sheet.cpp
parenta53847b7d27938551bb4f1c8891e7bacc93143ee (diff)
downloadopie-d2b982a38091cbc7cd4eba0994ab6c5e3c7f7189.zip
opie-d2b982a38091cbc7cd4eba0994ab6c5e3c7f7189.tar.gz
opie-d2b982a38091cbc7cd4eba0994ab6c5e3c7f7189.tar.bz2
added opie-sheet
Diffstat (limited to 'noncore/apps/opie-sheet/sheet.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/opie-sheet/sheet.cpp849
1 files changed, 849 insertions, 0 deletions
diff --git a/noncore/apps/opie-sheet/sheet.cpp b/noncore/apps/opie-sheet/sheet.cpp
new file mode 100644
index 0000000..9526937
--- a/dev/null
+++ b/noncore/apps/opie-sheet/sheet.cpp
@@ -0,0 +1,849 @@
1#include "sheet.h"
2
3#include <qmainwindow.h>
4#include <qmessagebox.h>
5#include <math.h>
6
7#define DEFAULT_COL_WIDTH 50
8
9Sheet::Sheet(int numRows, int numCols, QWidget *parent)
10 :QTable(numRows, numCols, parent)
11{
12 defaultBorders.right=defaultBorders.bottom=QPen(Qt::gray, 1, Qt::SolidLine);
13 defaultCellData.data="";
14 defaultCellData.background=QBrush(Qt::white, Qt::SolidPattern);
15 defaultCellData.alignment=(Qt::AlignmentFlags)(Qt::AlignLeft | Qt::AlignTop);
16 defaultCellData.fontColor=Qt::black;
17 defaultCellData.font=font();
18 defaultCellData.borders=defaultBorders;
19
20 selectionNo=-1;
21 setSelectionMode(QTable::Single);
22
23 sheetData.setAutoDelete(TRUE);
24 clipboardData.setAutoDelete(TRUE);
25 for (int i=0; i<numCols; ++i)
26 horizontalHeader()->setLabel(i, getHeaderString(i+1), DEFAULT_COL_WIDTH);
27
28 connect(this, SIGNAL(currentChanged(int, int)), this, SLOT(slotCellSelected(int, int)));
29 connect(this, SIGNAL(valueChanged(int, int)), this, SLOT(slotCellChanged(int, int)));
30}
31
32Sheet::~Sheet()
33{
34}
35
36typeCellData *Sheet::findCellData(int row, int col)
37{
38 typeCellData *tempCellData;
39 for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
40 if (tempCellData->row==row && tempCellData->col==col)
41 return tempCellData;
42 return NULL;
43}
44
45void Sheet::slotCellSelected(int row, int col)
46{
47 typeCellData *cellData=findCellData(row, col);
48 if (cellData)
49 emit currentDataChanged(cellData->data);
50 else
51 emit currentDataChanged("");
52}
53
54typeCellData *Sheet::createCellData(int row, int col)
55{
56 if (row<0 || col<0) return NULL;
57 typeCellData *cellData=new typeCellData;
58 cellData->row=row;
59 cellData->col=col;
60 cellData->data=defaultCellData.data;
61 cellData->borders=defaultCellData.borders;
62 cellData->alignment=defaultCellData.alignment;
63 cellData->font=defaultCellData.font;
64 cellData->fontColor=defaultCellData.fontColor;
65 cellData->background=defaultCellData.background;
66 sheetData.append(cellData);
67 return cellData;
68}
69
70void Sheet::slotCellChanged(int row, int col)
71{
72 typeCellData *cellData=findCellData(row, col);
73 if (!cellData) cellData=createCellData(row, col);
74 if (cellData) cellData->data=text(row, col);
75 for (cellData=sheetData.first(); cellData; cellData=sheetData.next())
76 setText(cellData->row, cellData->col, dataParser(cellData->data));
77 emit sheetModified();
78}
79
80void Sheet::swapCells(int row1, int col1, int row2, int col2)
81{
82 typeCellData *cellData1=findCellData(row1, col1), *cellData2=findCellData(row2, col2);
83 if (!cellData1) cellData1=createCellData(row1, col1);
84 if (!cellData2) cellData2=createCellData(row2, col2);
85 if (cellData1 && cellData2)
86 {
87 QString tempData(cellData1->data);
88 cellData1->data=cellData2->data;
89 cellData2->data=tempData;
90 setText(cellData1->row, cellData1->col, dataParser(cellData1->data));
91 setText(cellData2->row, cellData2->col, dataParser(cellData2->data));
92 emit sheetModified();
93 }
94}
95
96QString Sheet::getParameter(const QString &parameters, int paramNo, bool giveError=FALSE, const QString funcName="")
97{
98 QString params(parameters);
99 int position;
100 for (int i=0; i<paramNo; ++i)
101 {
102 position=params.find(',');
103 if (position<0)
104 {
105 if (giveError) QMessageBox::critical(this, tr("Error"), tr("Too few arguments to function '"+funcName+'\''));
106 return QString();
107 }
108 params=params.mid(position+1);
109 }
110 position=params.find(',');
111 if (position<0) return params;
112 return params.left(position);
113}
114
115bool Sheet::findRange(const QString &variable1, const QString &variable2, int *row1, int *col1, int *row2, int *col2)
116{
117 int row, col;
118 if (!findRowColumn(variable1, row1, col1, TRUE) || !findRowColumn(variable2, row2, col2, TRUE)) return FALSE;
119 if (*row1>*row2)
120 {
121 row=*row1;
122 *row1=*row2;
123 *row2=row;
124 }
125 if (*col1>*col2)
126 {
127 col=*col1;
128 *col1=*col2;
129 *col2=col;
130 }
131 return TRUE;
132}
133
134bool Sheet::findRowColumn(const QString &variable, int *row, int *col, bool giveError=FALSE)
135{
136 int position=variable.find(QRegExp("\\d"));
137 if (position<1)
138 {
139 if (giveError) QMessageBox::critical(this, tr("Error"), tr("Invalid variable: '"+variable+'\''));
140 return FALSE;
141 }
142 *row=variable.mid(position).toInt()-1;
143 *col=getHeaderColumn(variable.left(position))-1;
144 return TRUE;
145}
146
147double Sheet::calculateVariable(const QString &variable)
148{
149 bool ok;
150 double tempResult=variable.toDouble(&ok);
151 if (ok) return tempResult;
152
153 int row, col;
154 return (findRowColumn(variable, &row, &col, TRUE) ? text(row, col).toDouble() : 0);
155}
156
157double Sheet::functionSum(const QString &param1, const QString &param2)
158{
159 int row1, col1, row2, col2, row, col;
160 if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0;
161
162 double result=0, tempResult;
163 bool ok;
164 for (row=row1; row<=row2; ++row)
165 for (col=col1; col<=col2; ++col)
166 {
167 tempResult=text(row, col).toDouble(&ok);
168 if (ok) result+=tempResult;
169 }
170
171 return result;
172}
173
174double Sheet::functionMin(const QString &param1, const QString &param2)
175{
176 int row1, col1, row2, col2, row, col;
177 if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0;
178
179 double min=0, tempMin;
180 bool ok, init=FALSE;
181 for (row=row1; row<=row2; ++row)
182 for (col=col1; col<=col2; ++col)
183 {
184 tempMin=text(row, col).toDouble(&ok);
185 if (ok && (!init || tempMin<min))
186 {
187 min=tempMin;
188 init=TRUE;
189 }
190 }
191
192 return min;
193}
194
195double Sheet::functionMax(const QString &param1, const QString &param2)
196{
197 int row1, col1, row2, col2, row, col;
198 if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0;
199
200 double max=0, tempMax;
201 bool ok, init=FALSE;
202 for (row=row1; row<=row2; ++row)
203 for (col=col1; col<=col2; ++col)
204 {
205 tempMax=text(row, col).toDouble(&ok);
206 if (ok && (!init || tempMax>max))
207 {
208 max=tempMax;
209 init=TRUE;
210 }
211 }
212
213 return max;
214}
215
216double Sheet::functionAvg(const QString &param1, const QString &param2)
217{
218 double resultSum=functionSum(param1, param2), resultCount=functionCount(param1, param2);
219 return (resultCount>0 ? resultSum/resultCount : 0);
220}
221
222double Sheet::functionCount(const QString &param1, const QString &param2)
223{
224 int row1, col1, row2, col2, row, col;
225 if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0;
226
227 int divider=0;
228 bool ok;
229 for (row=row1; row<=row2; ++row)
230 for (col=col1; col<=col2; ++col)
231 {
232 text(row, col).toDouble(&ok);
233 if (ok) ++divider;
234 }
235
236 return divider;
237}
238
239double Sheet::calculateFunction(const QString &function, const QString &parameters)
240{
241 if (function=="+")
242 return calculateVariable(getParameter(parameters, 0))+calculateVariable(getParameter(parameters, 1));
243 if (function=="-")
244 return calculateVariable(getParameter(parameters, 0))-calculateVariable(getParameter(parameters, 1));
245 if (function=="*")
246 return calculateVariable(getParameter(parameters, 0))*calculateVariable(getParameter(parameters, 1));
247 if (function=="/")
248 return calculateVariable(getParameter(parameters, 0))/calculateVariable(getParameter(parameters, 1));
249 if (function=="SUM")
250 return functionSum(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
251 if (function=="COUNT")
252 return functionCount(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
253 if (function=="MIN")
254 return functionMin(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
255 if (function=="MAX")
256 return functionMax(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
257 if (function=="AVG")
258 return functionAvg(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
259 if (function=="ABS")
260 return fabs(calculateVariable(getParameter(parameters, 0, TRUE, function)));
261 if (function=="SIN")
262 return sin(calculateVariable(getParameter(parameters, 0, TRUE, function)));
263 if (function=="COS")
264 return cos(calculateVariable(getParameter(parameters, 0, TRUE, function)));
265 if (function=="TAN")
266 return tan(calculateVariable(getParameter(parameters, 0, TRUE, function)));
267 if (function=="ATAN")
268 return atan(calculateVariable(getParameter(parameters, 0, TRUE, function)));
269 if (function=="ATAN2")
270 return atan2(calculateVariable(getParameter(parameters, 0, TRUE, function)), calculateVariable(getParameter(parameters, 1, TRUE, function)));
271 if (function=="ASIN")
272 return asin(calculateVariable(getParameter(parameters, 0, TRUE, function)));
273 if (function=="ACOS")
274 return acos(calculateVariable(getParameter(parameters, 0, TRUE, function)));
275 if (function=="EXP")
276 return exp(calculateVariable(getParameter(parameters, 0, TRUE, function)));
277 if (function=="LOG")
278 return log(calculateVariable(getParameter(parameters, 0, TRUE, function)));
279 if (function=="POW")
280 return pow(calculateVariable(getParameter(parameters, 0, TRUE, function)), calculateVariable(getParameter(parameters, 1, TRUE, function)));
281 return 0;
282}
283
284int Sheet::getOperatorPriority(char oper)
285{
286 switch (oper)
287 {
288 case '+':
289 case '-':
290 return 1;
291
292 case '*':
293 case '/':
294 return 2;
295 }
296 return 0;
297}
298
299void Sheet::pushCharStack(QStack<QChar> *stackChars, const QChar &character)
300{
301 QChar *temp=new QChar(character);
302 stackChars->push(temp);
303}
304
305void Sheet::pushStringStack(QStack<QString> *stackStrings, const QString &string)
306{
307 QString *temp=new QString(string);
308 stackStrings->push(temp);
309}
310
311QChar Sheet::popCharStack(QStack<QChar> *stackChars)
312{
313 if (stackChars->isEmpty())
314 {
315 QMessageBox::critical(this, tr("Error"), tr("Syntax error!"));
316 return '0';
317 }
318
319 QChar *temp=stackChars->pop();
320 QChar temp2(*temp);
321 delete temp;
322 return temp2;
323}
324
325QString Sheet::popStringStack(QStack<QString> *stackStrings)
326{
327 if (stackStrings->isEmpty())
328 {
329 QMessageBox::critical(this, tr("Error"), tr("Syntax error!"));
330 return "0";
331 }
332
333 QString *temp=stackStrings->pop();
334 QString temp2(*temp);
335 delete temp;
336 return temp2;
337}
338
339QString Sheet::dataParserHelper(const QString &data)
340{
341 QStack<QString> stackElements;
342 QStack<QChar> stackOperators;
343 QString tempElement(""), temp2Element, firstElement, secondElement;
344 int paranCount;
345
346 for (unsigned int i=0; i<data.length(); ++i)
347 {
348 if (data[i]=='+' || data[i]=='-' || data[i]=='*' || data[i]=='/')
349 {
350 pushStringStack(&stackElements, tempElement);
351 tempElement="";
352 if (!stackOperators.isEmpty() && getOperatorPriority(*stackOperators.top())>getOperatorPriority(data[i]))
353 {
354 secondElement=popStringStack(&stackElements);
355 firstElement=popStringStack(&stackElements);
356 pushStringStack(&stackElements, QString::number(calculateFunction(popCharStack(&stackOperators), firstElement+","+secondElement)));
357 }
358 pushCharStack(&stackOperators, data[i]);
359 }
360 else
361 if (data[i]==',')
362 {
363 if (!tempElement.isEmpty()) pushStringStack(&stackElements, tempElement);
364 while (!stackOperators.isEmpty())
365 {
366 secondElement=popStringStack(&stackElements);
367 firstElement=popStringStack(&stackElements);
368 pushStringStack(&stackElements, QString::number(calculateFunction(popCharStack(&stackOperators), firstElement+","+secondElement)));
369 }
370 tempElement="";
371 }
372 else
373 if (data[i]=='(')
374 {
375 paranCount=1;
376 temp2Element="";
377 for (++i; paranCount>0; ++i)
378 {
379 temp2Element+=data[i];
380 if (data[i]=='(') ++paranCount;
381 if (data[i]==')') --paranCount;
382 }
383 temp2Element=dataParserHelper(temp2Element.left(temp2Element.length()-1));
384 if (tempElement.isEmpty())
385 tempElement=temp2Element;
386 else
387 tempElement.setNum(calculateFunction(tempElement, temp2Element));
388 --i;
389 }
390 else
391 tempElement+=data[i];
392 }
393 if (!tempElement.isEmpty()) pushStringStack(&stackElements, tempElement);
394 while (!stackOperators.isEmpty())
395 {
396 secondElement=popStringStack(&stackElements);
397 firstElement=popStringStack(&stackElements);
398 pushStringStack(&stackElements, QString::number(calculateFunction(popCharStack(&stackOperators), firstElement+","+secondElement)));
399 }
400
401 if (!stackElements.isEmpty())
402 tempElement=popStringStack(&stackElements);
403 while (!stackElements.isEmpty())
404 tempElement.prepend(popStringStack(&stackElements)+",");
405 return tempElement;
406}
407
408QString Sheet::dataParser(const QString &data)
409{
410 QString strippedData(data);
411 strippedData.replace(QRegExp("\\s"), "");
412 if (strippedData.isEmpty() || strippedData[0]!='=') return data;
413 strippedData=dataParserHelper(strippedData.remove(0, 1).upper().replace(QRegExp(":"), ","));
414
415 int i=0;
416 QString tempParameter(getParameter(strippedData, i)), result="";
417 do
418 {
419 result+=","+QString::number(calculateVariable(tempParameter));
420 tempParameter=getParameter(strippedData, ++i);
421 }
422 while (!tempParameter.isNull());
423 return result.mid(1);
424}
425
426void Sheet::setData(const QString &data)
427{
428 setText(currentRow(), currentColumn(), data);
429 slotCellChanged(currentRow(), currentColumn());
430 activateNextCell();
431}
432
433QString Sheet::getData()
434{
435 typeCellData *cellData=findCellData(currentRow(), currentColumn());
436 if (cellData)
437 return cellData->data;
438 return "";
439}
440
441void Sheet::lockClicks(bool lock=TRUE)
442{
443 clicksLocked=lock;
444}
445
446void Sheet::paintCell(QPainter *p, int row, int col, const QRect & cr, bool selected)
447{
448 if (selected && row==currentRow() && col==currentColumn()) selected=FALSE;
449
450 int sheetDataCurrent=sheetData.at();
451 typeCellData *cellData=findCellData(row, col);
452 if (sheetDataCurrent>=0) sheetData.at(sheetDataCurrent);
453 if (!cellData) cellData=&defaultCellData;
454 if (selected)
455 p->fillRect(0, 0, cr.width(), cr.height(), colorGroup().highlight());
456 else
457 {
458 p->fillRect(0, 0, cr.width(), cr.height(), colorGroup().base());
459 p->fillRect(0, 0, cr.width(), cr.height(), cellData->background);
460 }
461
462 QTableItem *cellItem=item(row, col);
463 if (cellItem)
464 {
465 p->setPen(selected ? colorGroup().highlightedText() : cellData->fontColor);
466 p->setFont(cellData->font);
467 p->drawText(2, 2, cr.width()-4, cr.height()-4, cellData->alignment, cellItem->text());
468 }
469
470 int rx=cr.width()-1, ry=cr.height()-1;
471 QPen pen(p->pen());
472 p->setPen(cellData->borders.right);
473 p->drawLine(rx, 0, rx, ry);
474 p->setPen(cellData->borders.bottom);
475 p->drawLine(0, ry, rx, ry);
476 p->setPen(pen);
477}
478
479void Sheet::viewportMousePressEvent(QMouseEvent *e)
480{
481 QMouseEvent ce(e->type(), viewportToContents(e->pos()), e->globalPos(), e->button(), e->state());
482 if (clicksLocked)
483 {
484 if (selectionNo<0)
485 {
486 clearSelection();
487 QTableSelection newSelection;
488 newSelection.init(rowAt(ce.pos().y()), columnAt(ce.pos().x()));
489 newSelection.expandTo(newSelection.anchorRow(), newSelection.anchorCol());
490 selectionNo=addSelection(newSelection);
491 }
492 }
493 else
494 QTable::contentsMousePressEvent(&ce);
495}
496
497void Sheet::viewportMouseMoveEvent(QMouseEvent *e)
498{
499 QMouseEvent ce(e->type(), viewportToContents(e->pos()), e->globalPos(), e->button(), e->state());
500 if (clicksLocked)
501 {
502 if (selectionNo>=0)
503 {
504 QTableSelection oldSelection(selection(selectionNo));
505 oldSelection.expandTo(rowAt(ce.pos().y()), columnAt(ce.pos().x()));
506 if (!(oldSelection==selection(selectionNo)))
507 {
508 removeSelection(selectionNo);
509 selectionNo=addSelection(oldSelection);
510 }
511 }
512 }
513 else
514 QTable::contentsMouseMoveEvent(&ce);
515}
516
517void Sheet::viewportMouseReleaseEvent(QMouseEvent *e)
518{
519 QMouseEvent ce(e->type(), viewportToContents(e->pos()), e->globalPos(), e->button(), e->state());
520 if (clicksLocked && selectionNo>=0)
521 {
522 QTableSelection oldSelection(selection(selectionNo));
523 oldSelection.expandTo(rowAt(ce.pos().y()), columnAt(ce.pos().x()));
524 removeSelection(selectionNo);
525 selectionNo=-1;
526 if (oldSelection.topRow()==oldSelection.bottomRow() && oldSelection.leftCol()==oldSelection.rightCol())
527 emit cellClicked(getHeaderString(oldSelection.leftCol()+1)+QString::number(oldSelection.topRow()+1));
528 else
529 emit cellClicked(getHeaderString(oldSelection.leftCol()+1)+QString::number(oldSelection.topRow()+1)+','+getHeaderString(oldSelection.rightCol()+1)+QString::number(oldSelection.bottomRow()+1));
530 }
531 else
532 QTable::contentsMouseReleaseEvent(&ce);
533}
534
535void Sheet::copySheetData(QList<typeCellData> *destSheetData)
536{
537 typeCellData *tempCellData, *newCellData;
538 destSheetData->clear();
539
540 for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
541 {
542 newCellData=new typeCellData;
543 *newCellData=*tempCellData;
544 destSheetData->append(newCellData);
545 }
546}
547
548void Sheet::setSheetData(QList<typeCellData> *srcSheetData)
549{
550 typeCellData *tempCellData, *newCellData;
551
552 for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
553 {
554 clearCell(tempCellData->row, tempCellData->col);
555 updateCell(tempCellData->row, tempCellData->col);
556 }
557 sheetData.clear();
558
559 for (tempCellData=srcSheetData->first(); tempCellData; tempCellData=srcSheetData->next())
560 {
561 newCellData=new typeCellData;
562 *newCellData=*tempCellData;
563 sheetData.append(newCellData);
564 setText(newCellData->row, newCellData->col, dataParser(newCellData->data));
565 }
566 emit sheetModified();
567}
568
569void Sheet::setName(const QString &name)
570{
571 sheetName=name;
572 emit sheetModified();
573}
574
575QString Sheet::getName()
576{
577 return sheetName;
578}
579
580void Sheet::setBrush(int row, int col, const QBrush &brush)
581{
582 typeCellData *cellData=findCellData(row, col);
583 if (!cellData) cellData=createCellData(row, col);
584 if (cellData)
585 {
586 cellData->background=brush;
587 emit sheetModified();
588 }
589}
590
591QBrush Sheet::getBrush(int row, int col)
592{
593 typeCellData *cellData=findCellData(row, col);
594 if (!cellData) cellData=&defaultCellData;
595 return cellData->background;
596}
597
598void Sheet::setTextAlign(int row, int col, Qt::AlignmentFlags flags)
599{
600 typeCellData *cellData=findCellData(row, col);
601 if (!cellData) cellData=createCellData(row, col);
602 if (cellData)
603 {
604 cellData->alignment=flags;
605 emit sheetModified();
606 }
607}
608
609Qt::AlignmentFlags Sheet::getAlignment(int row, int col)
610{
611 typeCellData *cellData=findCellData(row, col);
612 if (!cellData) cellData=&defaultCellData;
613 return cellData->alignment;
614}
615
616void Sheet::setTextFont(int row, int col, const QFont &font, const QColor &color)
617{
618 typeCellData *cellData=findCellData(row, col);
619 if (!cellData) cellData=createCellData(row, col);
620 if (cellData)
621 {
622 cellData->font=font;
623 cellData->fontColor=color;
624 emit sheetModified();
625 }
626}
627
628QFont Sheet::getFont(int row, int col)
629{
630 typeCellData *cellData=findCellData(row, col);
631 if (!cellData) cellData=&defaultCellData;
632 return cellData->font;
633}
634
635QColor Sheet::getFontColor(int row, int col)
636{
637 typeCellData *cellData=findCellData(row, col);
638 if (!cellData) cellData=&defaultCellData;
639 return cellData->fontColor;
640}
641
642void Sheet::setPen(int row, int col, int vertical, const QPen &pen)
643{
644 typeCellData *cellData=findCellData(row, col);
645 if (!cellData) cellData=createCellData(row, col);
646 if (cellData)
647 {
648 if (vertical)
649 cellData->borders.right=pen;
650 else
651 cellData->borders.bottom=pen;
652 emit sheetModified();
653 }
654}
655
656QPen Sheet::getPen(int row, int col, int vertical)
657{
658 typeCellData *cellData=findCellData(row, col);
659 if (!cellData) cellData=&defaultCellData;
660 return (vertical ? cellData->borders.right : cellData->borders.bottom);
661}
662
663void Sheet::getSelection(int *row1, int *col1, int *row2, int *col2)
664{
665 int selectionNo=currentSelection();
666 if (selectionNo>=0)
667 {
668 QTableSelection selection(selection(selectionNo));
669 *row1=selection.topRow();
670 *row2=selection.bottomRow();
671 *col1=selection.leftCol();
672 *col2=selection.rightCol();
673 }
674 else
675 {
676 *row1=*row2=currentRow();
677 *col1=*col2=currentColumn();
678 }
679}
680
681void Sheet::editClear()
682{
683 int row1, row2, col1, col2;
684 getSelection(&row1, &col1, &row2, &col2);
685
686 int row, col;
687 for (row=row1; row<=row2; ++row)
688 for (col=col1; col<=col2; ++col)
689 {
690 setText(row, col, "");
691 slotCellChanged(row, col);
692 }
693}
694
695void Sheet::editCopy()
696{
697 clipboardData.clear();
698
699 int row1, row2, col1, col2;
700 getSelection(&row1, &col1, &row2, &col2);
701
702 typeCellData *cellData, *newCellData;
703 int row, col;
704 for (row=row1; row<=row2; ++row)
705 for (col=col1; col<=col2; ++col)
706 {
707 cellData=findCellData(row, col);
708 if (cellData)
709 {
710 newCellData=new typeCellData;
711 *newCellData=*cellData;
712 newCellData->row-=row1;
713 newCellData->col-=col1;
714 clipboardData.append(newCellData);
715 }
716 }
717}
718
719void Sheet::editCut()
720{
721 editCopy();
722 editClear();
723}
724
725void Sheet::editPaste(bool onlyContents=FALSE)
726{
727 int row1=currentRow(), col1=currentColumn();
728 typeCellData *cellData, *tempCellData;
729
730 for (tempCellData=clipboardData.first(); tempCellData; tempCellData=clipboardData.next())
731 {
732 cellData=findCellData(tempCellData->row+row1, tempCellData->col+col1);
733 if (!cellData) cellData=createCellData(tempCellData->row+row1, tempCellData->col+col1);
734 if (cellData)
735 {
736 if (onlyContents)
737 cellData->data=tempCellData->data;
738 else
739 {
740 *cellData=*tempCellData;
741 cellData->row+=row1;
742 cellData->col+=col1;
743 }
744 setText(cellData->row, cellData->col, dataParser(cellData->data));
745 emit sheetModified();
746 }
747 }
748}
749
750void Sheet::insertRows(int no=1, bool allColumns=TRUE)
751{
752 setNumRows(numRows()+no);
753
754 typeCellData *tempCellData;
755 int row=currentRow(), col=currentColumn();
756
757 for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
758 if (tempCellData->row>=row && (allColumns || tempCellData->col==col))
759 {
760 clearCell(tempCellData->row, tempCellData->col);
761 tempCellData->row+=no;
762 }
763 for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
764 if (tempCellData->row>=row && (allColumns || tempCellData->col==col))
765 {
766 updateCell(tempCellData->row-no, tempCellData->col);
767 setText(tempCellData->row, tempCellData->col, dataParser(tempCellData->data));
768 }
769 emit sheetModified();
770}
771
772void Sheet::insertColumns(int no=1, bool allRows=TRUE)
773{
774 int noCols=numCols();
775 int newCols=noCols+no;
776 setNumCols(newCols);
777 for (int i=noCols; i<newCols; ++i)
778 horizontalHeader()->setLabel(i, getHeaderString(i+1), DEFAULT_COL_WIDTH);
779
780 typeCellData *tempCellData;
781 int col=currentColumn(), row=currentRow();
782
783 for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
784 if (tempCellData->col>=col && (allRows || tempCellData->row==row))
785 {
786 clearCell(tempCellData->row, tempCellData->col);
787 tempCellData->col+=no;
788 }
789 for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
790 if (tempCellData->col>=col && (allRows || tempCellData->row==row))
791 {
792 updateCell(tempCellData->row, tempCellData->col-no);
793 setText(tempCellData->row, tempCellData->col, dataParser(tempCellData->data));
794 }
795 emit sheetModified();
796}
797
798void Sheet::dataFindReplace(const QString &findStr, const QString &replaceStr, bool matchCase=TRUE, bool allCells=TRUE, bool entireCell=FALSE, bool replace=FALSE, bool replaceAll=FALSE)
799{
800 typeCellData *tempCellData;
801 int row1, col1, row2, col2;
802 getSelection(&row1, &col1, &row2, &col2);
803 bool found=FALSE;
804
805 for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
806 if (allCells || (tempCellData->row>=row1 && tempCellData->row<=row2 && tempCellData->col>=col1 && tempCellData->col<=col2))
807 {
808 QTableItem *cellItem=item(tempCellData->row, tempCellData->col);
809 if (cellItem && (entireCell ? (matchCase ? cellItem->text()==findStr : cellItem->text().upper()==findStr.upper()) : cellItem->text().find(findStr, 0, matchCase)>=0))
810 {
811 if (!found)
812 {
813 found=TRUE;
814 clearSelection();
815 }
816 setCurrentCell(tempCellData->row, tempCellData->col);
817 if (replace)
818 {
819 tempCellData->data=cellItem->text().replace(QRegExp(findStr, matchCase), replaceStr);
820 setText(tempCellData->row, tempCellData->col, dataParser(tempCellData->data));
821 }
822 if (!replace || !replaceAll) break;
823 }
824 }
825
826 if (found)
827 {
828 if (replace)
829 slotCellChanged(currentRow(), currentColumn());
830 }
831 else
832 QMessageBox::warning(this, tr("Error"), tr("Search key not found!"));
833}
834
835//
836// Static functions
837//
838
839QString Sheet::getHeaderString(int section)
840{
841 if (section<1) return "";
842 return getHeaderString((section-1)/26)+QChar('A'+(section-1)%26);
843}
844
845int Sheet::getHeaderColumn(const QString &section)
846{
847 if (section.isEmpty()) return 0;
848 return (section[section.length()-1]-'A'+1)+getHeaderColumn(section.left(section.length()-1))*26;
849}