kword

KWTableFrameSet.cpp
1/*
2 Copyright (C) 2001, S.R.Haque (srhaque@iee.org).
3 This file is part of the KDE project
4 Copyright (C) 2005 Thomas Zander <zander@kde.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20
21DESCRIPTION
22
23 This file implements KWord tables.
24*/
25
26// ### TODO : multi page tables
27
28#include "KWTableFrameSet.h"
29#include "KWDocument.h"
30#include "KWAnchor.h"
31#include "KWCanvas.h"
32#include "KWCommand.h"
33#include "KWViewMode.h"
34#include "KWView.h"
35#include "KWordFrameSetIface.h"
36#include "KWordTableFrameSetIface.h"
37#include "KWFrameList.h"
38#include "KWPageManager.h"
39#include "KWPage.h"
40#include "KWOasisSaver.h"
41
42#include <KoOasisContext.h>
43#include <KoXmlWriter.h>
44#include <KoDom.h>
45#include <KoXmlNS.h>
46#include <KoTextObject.h> // for customItemChar !
47#include <KoTextParag.h>
48
49#include <tdemessagebox.h>
50#include <kdebug.h>
51#include <tdelocale.h>
52#include <dcopobject.h>
53#include <tqapplication.h>
54#include <tqpopupmenu.h>
55#include <tqclipboard.h>
56
57
58KWTableFrameSet::KWTableFrameSet( KWDocument *doc, const TQString & name ) :
59 KWFrameSet( doc )
60{
61 m_rows = m_cols = m_nr_cells = 0;
62 m_name = TQString();
63 m_active = true;
64 m_frames.setAutoDelete(false);
65 if ( name.isEmpty() )
66 m_name = doc->generateFramesetName( i18n( "Table %1" ) );
67 else
68 m_name = name;
69}
70
72{
73 m_doc = 0L;
74}
75
76KWordFrameSetIface* KWTableFrameSet::dcopObject()
77{
78 if ( !m_dcop )
79 m_dcop = new KWordTableFrameSetIface( this );
80
81 return m_dcop;
82}
83
84
86{
87 return new KWTableFrameSetEdit( this, canvas );
88}
89
91{
92 for(TableIter c(this); c; ++c)
93 c.current()->updateFrames( flags );
94 if ( isFloating() ) {
95 KWAnchor * anchor = findAnchor( 0 );
96 if ( anchor )
97 anchor->resize();
98 }
99
101}
102
103void KWTableFrameSet::moveFloatingFrame( int /*frameNum TODO */, const KoPoint &position )
104{
105 // TODO multi-page case
106
107 double dx = position.x() - m_colPositions[0];
108 double dy = position.y() - m_rowPositions[0];
109
110 KWTableFrameSet::Cell *daCell = cell(0,0);
111 Q_ASSERT(daCell);
112 if (! daCell) return; //hack to work around https://bugs.kde.org/show_bug.cgi?id=67216
113 int oldPageNumber = daCell->frame(0)->pageNumber();
114 // TODO multi-page case
115
116 moveBy( dx, dy );
117
118 if ( dx || dy ) {
119 updateFrames();
120 cell(0,0)->frame(0)->frameStack()->updateAfterMove( oldPageNumber );
121 }
122}
123
124KoSize KWTableFrameSet::floatingFrameSize( int /*frameNum*/ )
125{
126 return boundingRect().size();
127}
128
130{
131 return new KWCreateTableCommand( i18n("Create Table"), this );
132}
133
135{
136 return new KWDeleteTableCommand( i18n("Delete Table"), this );
137}
138
139KWAnchor * KWTableFrameSet::createAnchor( KoTextDocument *txt, int frameNum )
140{
141 //kdDebug(32004) << "KWTableFrameSet::createAnchor" << endl;
142 return new KWAnchor( txt, this, frameNum );
143}
144
145void KWTableFrameSet::createAnchors( KoTextParag * parag, int index, bool placeHolderExists /*= false */ /*only used when loading*/,
146 bool repaint )
147{
148 //kdDebug(32004) << "KWTableFrameSet::createAnchors" << endl;
149 // TODO make one rect per page, and create one anchor per page
150 // Anchor this frame, after the previous one
151 KWAnchor * anchor = createAnchor( m_anchorTextFs->textDocument(), 0 );
152 if ( !placeHolderExists )
153 parag->insert( index, KoTextObject::customItemChar() );
154 parag->setCustomItem( index, anchor, 0 );
155 kdDebug(32004) << "KWTableFrameSet::createAnchors setting anchor" << endl;
156 parag->setChanged( true );
157 if ( repaint )
158 emit repaintChanged( m_anchorTextFs );
159}
160
161void KWTableFrameSet::deleteAnchors()
162{
163 KWAnchor * anchor = findAnchor( 0 );
164 kdDebug(32004) << "KWTableFrameSet::deleteAnchors anchor=" << anchor << endl;
165 deleteAnchor( anchor );
166}
167
168
169void KWTableFrameSet::addCell( Cell* daCell ) // called add but also used to 'update'
170{
171 m_rows = kMax( daCell->rowAfter(), m_rows );
172 m_cols = kMax( daCell->columnAfter(), m_cols );
173
174 if ( m_rowArray.size() < daCell->rowAfter() )
175 m_rowArray.resize( daCell->rowAfter() );
176 for ( uint row = daCell->firstRow() ;row < daCell->rowAfter(); ++row )
177 {
178 if ( !m_rowArray[ row ] )
179 m_rowArray.insert( row, new Row );
180 m_rowArray[ row ]->addCell( daCell );
181 }
182}
183
185{
186 for ( uint row = daCell->firstRow() ; row < daCell->rowAfter(); ++row )
187 m_rowArray[ row ]->removeCell( daCell );
188}
189
190void KWTableFrameSet::insertRowVector(uint index, Row *r)
191{
192 if(m_rowArray.size() < m_rowArray.count() + 1)
193 m_rowArray.resize(m_rowArray.count() + 1);
194
195 for(uint i = m_rowArray.count(); i > index; i--)
196 m_rowArray.insert(i, m_rowArray[i-1]);
197
198 m_rowArray.insert(index, r);
199}
200
201/*
202 * Inserts a new (empty) element into each row vector.
203 * Elements in a row vector after index are moved back.
204 */
205void KWTableFrameSet::insertEmptyColumn(uint index)
206{
207 for(uint i = 0; i < m_rowArray.count(); ++i) {
208 Row *r = m_rowArray[i];
209 if(r->m_cellArray.size() < m_cols + 1)
210 r->m_cellArray.resize(m_cols + 1);
211 for(int j = m_cols - 1; j >= (int)index; --j)
212 r->m_cellArray.insert(j + 1, r->m_cellArray[j]);
213 r->m_cellArray.insert(index, 0);
214 }
215}
216
218KWTableFrameSet::removeRowVector(uint index)
219{
220 Q_ASSERT(index < m_rowArray.count() );
221 Row *ret = m_rowArray.at(index);
222 Row *r;
223 for(uint i = index; i < m_rowArray.size() - 1; ++i){
224 r = m_rowArray.at(i+1);
225 m_rowArray.remove(i+1);
226 m_rowArray.insert(i,r);
227 }
228 return ret;
229}
230
231
233 KoRect outerRect(m_colPositions[0], // left
234 m_rowPositions[0], // top
235 m_colPositions.last()-m_colPositions[0], // width
236 m_rowPositions.last()-m_rowPositions[0]);// height
237
238 // Add 1 'pixel' (at current zoom level) like KWFrame::outerKoRect(),
239 // to avoid that the bottom line disappears due to rounding problems
240 // (i.e. that it doesn't fit in the calculated paragraph height in pixels,
241 // which depends on the paragraph's Y position)
242 // Better have one pixel too much (caret looks too big by one pixel)
243 // than one missing (bottom line of cell not painted)
244 outerRect.rRight() += m_doc->zoomItX( 1 ) / m_doc->zoomedResolutionX();
245 outerRect.rBottom() += m_doc->zoomItY( 1 ) / m_doc->zoomedResolutionY();
246
247 return outerRect;
248
249}
250
252{
253 double top = 0.0;
254 for (uint i = 0; i < getColumns(); i++)
255 {
256 KWTableFrameSet::Cell *daCell = cell( 0, i );
257 top = kMax( top, m_rowPositions[0] + daCell->topBorder() );
258 }
259 return top;
260}
261
262
264{
265 double left = 0.0;
266 for (uint i=0; i < getRows(); i++)
267 {
268 KWTableFrameSet::Cell *daCell = cell( i, 0 );
269 left = kMax( left, m_colPositions[0] + daCell->leftBorder() );
270 }
271 return left;
272}
273
274/* returns the cell that occupies row, col. */
275KWTableFrameSet::Cell *KWTableFrameSet::cell( unsigned int row, unsigned int col ) const
276{
277 if ( row < m_rowArray.size() && col < m_rowArray[row]->size() ) {
278 Cell* cell = (*m_rowArray[row])[col];
279 if ( cell )
280 return cell;
281 }
282// kdWarning() << name() << " cell " << row << "," << col << " => returning 0!" << kdBacktrace( 3 ) << endl;
283//#ifndef NDEBUG
284// validate();
285// printArrayDebug();
286//#endif
287 return 0L;
288}
289
290KWTableFrameSet::Cell *KWTableFrameSet::cellByPos( double x, double y ) const
291{
292 KWFrame *f = frameAtPos(x,y);
293 if(f) return static_cast<KWTableFrameSet::Cell *> (f->frameSet());
294 return 0L;
295}
296
297void KWTableFrameSet::recalcCols(unsigned int col,unsigned int row) {
298 if(col >= getColumns())
299 col = getColumns()-1;
300 if(row >= getRows())
301 row = getRows()-1;
302 Cell *activeCell = cell(row,col);
303 Q_ASSERT( activeCell );
304 if ( !activeCell )
305 return;
306 double difference = 0;
307
308 if(activeCell->frame(0)->left() - activeCell->leftBorder() != m_colPositions[activeCell->firstColumn()]) {
309 // left border moved.
310 col = activeCell->firstRow();
311 difference = 0-(activeCell->frame(0)->left() - activeCell->leftBorder() - m_colPositions[activeCell->firstColumn()]);
312 }
313
314 if(activeCell->frame(0)->right() - activeCell->rightBorder() !=
315 m_colPositions[activeCell->lastColumn()]) { // right border moved
316
317 col = activeCell->columnAfter();
318 double difference2 = activeCell->frame(0)->right() + activeCell->rightBorder() - m_colPositions[activeCell->columnAfter()];
319
320 double moved=difference2+difference;
321 if(moved > -0.01 && moved < 0.01) { // we were simply moved.
322 col=0;
323 difference = difference2;
324 } else if(difference2!=0)
325 difference = difference2;
326 }
327
328 m_redrawFromCol=getColumns(); // possible reposition col starting with this one, done in recalcRows
329 if(difference!=0) {
330 double last=col==0?0:m_colPositions[col-1];
331 for(unsigned int i=col; i < m_colPositions.count(); i++) {
332 double &colPos = m_colPositions[i];
333 colPos = colPos + difference;
334 if(colPos-last < s_minFrameWidth) { // Never make it smaller then allowed!
335 difference += s_minFrameWidth - colPos;
336 colPos = s_minFrameWidth + last;
337 }
338 last=colPos;
339 }
340 m_redrawFromCol=col;
341 if(col>0) m_redrawFromCol--;
342 //if(activeCell) activeCell->frame(0)->setMinimumFrameHeight(0);
343 }
344 updateFrames();
345 //kdDebug(32004) << "end KWTableFrameSet::recalcCols" << endl;
346}
347
348
349// Step through the whole table and recalculate the position and size
350// of each cell.
351
352void KWTableFrameSet::recalcRows(unsigned int col, unsigned int row) {
353 kdDebug(32004) << name() << " KWTableFrameSet::recalcRows ("<< col <<"," << row << ")" << endl;
354 //for(unsigned int i=0; i < m_rowPositions.count() ; i++) kdDebug(32004) << "row: " << i << " = " << m_rowPositions[i] << endl;
355
356 Cell *activeCell = cell(row,col);
357 Q_ASSERT( activeCell );
358 if ( !activeCell ) // #122807
359 return;
360 double difference = 0;
361
362 if(activeCell->frame(0)->height() != activeCell->frame(0)->minimumFrameHeight() &&
363 activeCell->type() == FT_TEXT) {
364 // when the amount of text changed and the frame has to be rescaled we are also called.
365 // lets check the minimum size for all the cells in this row.
366
367 // Take a square of table cells which depend on each others height. It is always the full
368 // width of the table and the height is determined by joined cells, the minimum is one row.
369 double minHeightOtherCols=0; // The minimum height which the whole square of table cells can take
370 double minHeightActiveRow=0; // The minimum height our cell can get because of cells in his row
371 double minHeightMyCol=0; // The minimum height our column can get in the whole square
372 unsigned int rowSpan = activeCell->rowSpan();
373 unsigned int startRow = activeCell->firstRow();
374 for (uint colCount = 0; colCount < getColumns(); ++colCount )
375 {
376 // for each column
377 unsigned int rowCount=startRow;
378 double thisColHeight=0; // the total height of this column
379 double thisColActiveRow=0; // the total height of all cells in this col, completely in the
380 // row of the activeCell
381 do { // for each row (under startRow)
382 Cell *thisCell=cell(rowCount,colCount);
383 if ( !thisCell )
384 break; // ###
385 if(thisCell->firstRow() < startRow) { // above -> set startRow and restart
386 rowSpan += startRow - thisCell->firstRow();
387 startRow = thisCell->firstRow();
388 break;
389 }
390 if(thisCell->rowAfter() > startRow + rowSpan) {
391 rowSpan = thisCell->rowAfter() - startRow;
392 break;
393 }
394
395 thisColHeight+=thisCell->frame(0)->minimumFrameHeight();
396 thisColHeight+=thisCell->topBorder();
397 thisColHeight+=thisCell->bottomBorder();
398
399 if(thisCell->firstRow() >= activeCell->firstRow() && thisCell->rowAfter() <= activeCell->rowAfter())
400 thisColActiveRow+=thisCell->frame(0)->minimumFrameHeight();
401
402 rowCount += thisCell->rowSpan();
403 } while (rowCount < rowSpan+startRow);
404
405 if(colCount >= activeCell->firstColumn() &&
406 colCount < activeCell->columnAfter() )
407 minHeightMyCol = thisColHeight;
408 else {
409 minHeightOtherCols = kMax(minHeightOtherCols, thisColHeight);
410 minHeightActiveRow = kMax(minHeightActiveRow, thisColActiveRow);
411 }
412 } // for each column
413
414 bool bottomRow = (startRow+rowSpan == activeCell->rowAfter());
415 if(!bottomRow) {
416 Cell *bottomCell=cell(startRow+rowSpan-1, activeCell->firstColumn());
417 bottomCell->frame(0)->setHeight(bottomCell->frame(0)->minimumFrameHeight() +
418 minHeightOtherCols - minHeightMyCol);
419 // ### RECURSE ###
420 recalcRows(bottomCell->firstColumn(), bottomCell->firstRow());
421 }
422 if(activeCell->frame(0)->minimumFrameHeight() > activeCell->frame(0)->height()) { // wants to grow
423 activeCell->frame(0)->setHeight(activeCell->frame(0)->minimumFrameHeight());
424 //kdDebug(32004) << activeCell->name() << " grew to its minheight: " << activeCell->frame(0)->minimumFrameHeight() << endl;
425 } else { // wants to shrink
426 double newHeight=kMax(activeCell->frame(0)->minimumFrameHeight(),minHeightActiveRow);
427 if(bottomRow) // I'm a strech cell
428 newHeight=kMax(newHeight, minHeightOtherCols - (minHeightMyCol - activeCell->frame(0)->minimumFrameHeight()));
429 activeCell->frame(0)->setHeight(newHeight);
430 //kdDebug(32004) << activeCell->name() << " shrunk to: " << newHeight << endl;
431 }
432 }
433
434 if(activeCell->frame(0)->top() - activeCell->topBorder() != getPositionOfRow(activeCell->firstRow())) {
435 // top moved.
436 row = activeCell->firstRow();
437 difference = 0 - (activeCell->frame(0)->top() - activeCell->topBorder() - getPositionOfRow(row));
438 }
439
440
441 if(activeCell->frame(0)->bottom() + activeCell->bottomBorder() !=
442 getPositionOfRow(activeCell->rowAfter())) { // bottom moved
443
444 row = activeCell->rowAfter();
445 double difference2 = activeCell->frame(0)->bottom() + activeCell->bottomBorder() - getPositionOfRow(row);
446 double moved=difference2+difference;
447 if(moved > -0.01 && moved < 0.01) { // we were simply moved.
448 row=0;
449 difference = difference2;
450 } else if( difference2!=0)
451 difference = difference2;
452 }
453
454 unsigned int fromRow = m_rows; // possible reposition rows starting with this one, default to no repositioning
455 unsigned int untilRow=0; // possible reposition rows ending with this one
456 if( TQABS( difference ) > 1E-10 ) { // means "difference != 0.0"
457 TQValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
458 TQValueList<double>::iterator j = m_rowPositions.begin();
459 double last=0.0;
460 int lineNumber=-1;
461 while(j != m_rowPositions.end()) {
462 lineNumber++;
463 if(pageBound!=m_pageBoundaries.end()) {
464 if((int)*pageBound == lineNumber) { // next page
465 if(lineNumber >= (int)row) { // then delete line j
466 TQValueList<double>::iterator nextJ = j;
467 ++nextJ;
468 difference -= *(nextJ)-*(j);
469 kdDebug(32004) << "Deleting line with old pos: " << *j << endl;
470 j=m_rowPositions.remove(j);
471 j--;
472 TQValueList<unsigned int>::iterator tmp = pageBound;
473 ++pageBound;
474 m_pageBoundaries.remove(tmp);
475 j++;
476 continue;
477 }
478 ++pageBound;
479 lineNumber--;
480 }
481 }
482 if(lineNumber >= (int)row) { // below changed row
483 if(*(j)-last < s_minFrameHeight) // Never make it smaller then allowed!
484 difference += s_minFrameHeight - *(j) + last;
485 last=*(j);
486 kdDebug(32004) << "moving " << *(j) << " by " << difference << "; to " << (*j) + difference << endl;
487 (*j) += difference; // move line.
488 }
489 j++;
490 }
491 fromRow=row;
492 if(row>0) fromRow--;
493 } else {
494 row=0;
495 }
496#if 0
497{ TQValueList<unsigned int>::iterator pb = m_pageBoundaries.begin();
498 unsigned int i=0;
499 double last=0;
500 do {
501 double cur=m_rowPositions[i];
502 if(pb!=m_pageBoundaries.end() && *(pb)==i) {
503 kdDebug(32004) << "line: " << i << ": " << cur << " *" << (last>cur?" (ALERT)":"") << endl;
504 ++pb;
505 } else
506 kdDebug(32004) << "line: " << i << ": " << cur << (last>cur?" (ALERT)":"") << endl;
507 last=cur;
508 i++;
509 } while( i<m_rowPositions.count());
510}
511#endif
512#if 0 // def SUPPORT_MULTI_PAGE_TABLES
513
514 //double pageHeight = m_doc->ptPaperHeight() - m_doc->ptBottomBorder() - m_doc->ptTopBorder();
515 unsigned int pageNumber=cell(0,0)->frame(0)->pageNumber() +1;
516 unsigned int lineNumber=1;
517 TQValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
518 TQValueList<double>::iterator j = m_rowPositions.begin();
519
520 double diff=0.0;
521 double pageBottom = pageNumber * m_doc->ptPaperHeight() - m_doc->ptBottomBorder();
522 // kdDebug(32004) << "pageBottom; " << pageBottom << endl;
523 while(++j!=m_rowPositions.end()) { // stuff for multipage tables.
524 if(pageBound!=m_pageBoundaries.end() && *pageBound == lineNumber ) {
525 if(*j > pageNumber * m_doc->ptPaperHeight() - m_doc->ptBottomBorder() ) { // next page marker exists, and is accurate...
526 pageNumber++;
527 pageBottom = pageNumber * m_doc->ptPaperHeight() - m_doc->ptBottomBorder();
528 // kdDebug(32004) << "pageBottom; " << pageBottom << endl;
529 untilRow=kMax(untilRow, *pageBound);
530 pageBound++;
531 }
532 }
533
534//kdDebug() << "checking; " << lineNumber << ", " << (*j) << endl;
535 if((*j) + diff > pageBottom) { // a row falls off the page.
536//kdDebug(32004) << "row falls off of page"<< endl;
537 untilRow = m_rows;
538 bool hugeRow = false;
539 unsigned int breakRow = lineNumber-1;
540 // find out of no cells are spanning multiple rows meaning we have to break higher.
541#if 0
542 // ### TODO: I did not get a chance do debug this yet! TZ.
543 for(int i=0; i < getColumns() ; i++) {
544 kdDebug() << "i: " << i<< endl;
545 Cell *c= cell(breakRow, i);
546 kdDebug() << "c: " << c->firstRow() << "," << c->m_col << " w: " << c->columnSpan() << ", h: " << c->rowSpan() << endl;
547 if(c->firstRow() < breakRow) {
548 breakRow = c->firstRow();
549 i=-1;
550 }
551 }
552 kdDebug() << "breakRow: " << breakRow<< endl;
553 fromRow=kMin(fromRow, breakRow);
554 if(breakRow < lineNumber+1) {
555 for(unsigned int i=lineNumber+1; i > breakRow;i--)
556 kdDebug() << "j--";
557 for(unsigned int i=lineNumber+1; i > breakRow;i--)
558 --j;
559 lineNumber=breakRow+1;
560 }
561
562 // find out if the next row (the new one on the page) does not contain cells higher then page.
563 for(unsigned int i=0; i < getColumns() ; i++) {
564 if(cell(breakRow+1,i) && cell(breakRow+1,i)->frame(0)->height() > pageHeight)
565 hugeRow=true;
566 }
567 //if((*pageBound) != breakRow) { // I think that this has to be that way
568 // voeg top in in rowPositions
569#endif
570
571 double topOfPage = m_doc->ptPaperHeight() * pageNumber + m_doc->ptTopBorder();
572
573 TQValueList<double>::iterator tmp = m_rowPositions.at(breakRow);
574 diff += topOfPage - (*tmp); // diff between bottom of last row on page and top of new page
575//kdDebug() << "diff += " << topOfPage << " - " << (*tmp) << ". diff += " << topOfPage - (*tmp) <<" ="<< diff << endl;
576 lineNumber++;
577 m_rowPositions.insert(j, topOfPage);
578
579 // insert new pageBound. It points to last LINE on previous page
580 pageBound = m_pageBoundaries.insert(pageBound, breakRow);
581 //kdDebug(32004) << "inserting new pageBound: " << breakRow << " at " << m_rowPositions[breakRow] << endl;
582 pageBound++;
583 if(!hugeRow) {
584 // add header-rij toe. (en zet bool) TODO
585 //j++;
586 //lineNumber++;
587 // m_hasTmpHeaders = true;
588 }
589 pageNumber++;
590 pageBottom = pageNumber * m_doc->ptPaperHeight() - m_doc->ptBottomBorder();
591 //kdDebug(32004) << " pageBottom: " << pageBottom << " pageNumber=" << pageNumber << endl;
592 if((int)pageNumber > m_doc->numPages()) {
593 int num = m_doc->appendPage();
594 kdDebug(32004) << "Have appended page: " << num << " (one page mode!)" << endl;
595 m_doc->afterInsertPage( num );
596 }
597 }
598 //if(diff > 0) kdDebug(32004) << " adding " << diff << ", line " << lineNumber << " " << *(j) <<" -> " << *(j)+diff << endl;
599 if(diff > 0)
600 (*j) = (*j) + diff;
601 lineNumber++;
602
603#if 0 // def SUPPORT_MULTI_PAGE_TABLES
604 // Note: produces much ouput!
605 int i = 1; // DEBUG
606 for ( TQValueList<double>::iterator itDebug = m_rowPositions.begin(); itDebug != m_rowPositions.end(); ++itDebug, ++i )
607 {
608 kdDebug(32004) << "m_rowPosition[" << i << "]= " << (*itDebug) << endl;
609 }
610#endif
611
612 }
613#endif
614#if 0
615{ TQValueList<unsigned int>::iterator pb = m_pageBoundaries.begin();
616 unsigned int i=0;
617 double last=0;
618 do {
619 double cur=m_rowPositions[i];
620 if(pb!=m_pageBoundaries.end() && *(pb)==i) {
621 kdDebug(32004) << "line: " << i << ": " << cur << " *" << (last>cur?" (ALERT)":"") << endl;
622 ++pb;
623 } else
624 kdDebug(32004) << "line: " << i << ": " << cur << (last>cur?" (ALERT)":"") << endl;
625 last=cur;
626 i++;
627 } while( i<m_rowPositions.count());
628}
629#endif
630//for (unsigned int i=0; i < getRows(); kdDebug(32004)<<" pos of row["<<i<<"] = "<<getPositionOfRow(i)<<"/"<<getPositionOfRow(i,true)<<endl,i++);
631 //kdDebug () << "Repositioning from row : " << fromRow << " until: " << untilRow << endl;
632 //kdDebug () << "Repositioning from col > " << redrawFromCol << endl;
633 // do positioning.
634 //Cell *cell;
635 //bool setMinFrameSize= activeCell->frame(0)->isSelected();
636
637#if 0 // def SUPPORT_MULTI_PAGE_TABLES
638 for(TableIter cell(this); cell; ++cell) {
639 if((cell->rowAfter() > fromRow && cell->firstRow() < untilRow) || cell->columnAfter() > m_redrawFromCol)
640 position(cell, (cell==activeCell && cell->frame(0)->isSelected()));
641 }
642 m_redrawFromCol = getColumns();
643
644 // check if any rowPosition entries are unused
645
646 // first create a hash of all row entries
647 TQMap<unsigned int,int> rows; // rownr, count
648 unsigned int top=m_rowPositions.count() - m_pageBoundaries.count()-1;
649 for(unsigned int i=0; i < top; rows[i++]=0);
650
651 // fill hash with data
652 for(TableIter i(this); i; ++i) {
653 rows[i->firstRow()] += 1;
654 }
655 // check if some entries have stayed unused.
656 unsigned int counter=top;
657 int adjustment=m_pageBoundaries.count()-1;
658
659 do {
660 counter--;
661 if(adjustment >= 0 && counter == m_pageBoundaries[adjustment])
662 adjustment--;
663 if(rows[counter]==0) {
664 kdDebug() << k_funcinfo << "no rows at counter=" << counter << " -> erasing" << endl;
665 m_rows--;
666 m_rowPositions.erase(m_rowPositions.at(counter+(adjustment>0?adjustment:0)));
667 for (TableIter cell(this); cell; ++cell) {
668 if(cell->firstRow() < counter && cell->rowAfter() > counter)
669 cell->setRowSpan(cell->rowSpan()-1);
670 if(cell->firstRow() > counter)
671 cell->setFirstRow(cell->firstRow()-1);
672 }
673
674 if(adjustment >= -1) {
675 pageBound = m_pageBoundaries.at(adjustment+1);
676 while(pageBound!=m_pageBoundaries.end()) {
677 (*pageBound)= (*pageBound)-1;
678 pageBound++;
679 }
680 }
681 }
682 } while(counter!=0);
683#endif
684
685
686 m_redrawFromCol = 0;
687 for (TableIter cell(this); cell; ++cell) {
688 if((cell->rowAfter() > fromRow && cell->firstRow() < untilRow)
689 || cell->columnAfter() > m_redrawFromCol)
690 position(cell);
691 }
692 m_redrawFromCol = getColumns();
693 kdDebug(32004) << name() << " KWTableFrameSet::recalcRows done" << endl;
694 updateFrames();
695}
696
697int KWTableFrameSet::columnEdgeAt( double x ) const
698{
699 // We compare x with the middle of columns (left+right/2),
700 // to find which column x is closest to.
701 // m_colPositions is sorted, so we can remember the last column we looked at.
702 double lastMiddlePos = 0;
703 for ( uint i = 0; i < m_colPositions.count() - 1; i++ ) {
704 double middlePos = ( m_colPositions[i] + m_colPositions[i+1] ) / 2;
705 Q_ASSERT( lastMiddlePos < middlePos );
706 if ( x > lastMiddlePos && x <= middlePos )
707 return i;
708 lastMiddlePos = middlePos;
709 }
710 return m_colPositions.count() - 1;
711}
712
713int KWTableFrameSet::rowEdgeAt( double y ) const
714{
715 double lastMiddlePos = 0;
716 for ( uint i = 0; i < m_rowPositions.count() - 1; i++ ) {
717 double middlePos = ( m_rowPositions[i] + m_rowPositions[i+1] ) / 2;
718 Q_ASSERT( lastMiddlePos < middlePos );
719 if ( y > lastMiddlePos && y <= middlePos )
720 return i;
721 lastMiddlePos = middlePos;
722 }
723 return m_rowPositions.count() - 1;
724}
725
726double KWTableFrameSet::columnSize( unsigned int col )
727{
728 return m_colPositions[ col ];
729}
730
731double KWTableFrameSet::rowSize( unsigned int row )
732{
733 return m_rowPositions[ row ];
734}
735
736void KWTableFrameSet::resizeColumn( unsigned int col, double x )
737{
738 kdDebug() << k_funcinfo << col << "," << x << endl;
739 if ((col != 0) && (x - m_colPositions[ col-1 ] < s_minFrameWidth))
740 m_colPositions[ col ] = m_colPositions[ col-1 ] + s_minFrameWidth;
741 else
742 if ((col != getColumns()) && (m_colPositions[ col + 1 ] - x < s_minFrameWidth))
743 m_colPositions[col] = m_colPositions[ col + 1 ] - s_minFrameWidth;
744 else
745 m_colPositions[ col ] = x;
746
747 // move all cells right of 'col'
748 for (TableIter cell(this); cell; ++cell) {
749 if ( cell->columnAfter() >= col ) {
750 position(cell);
751 }
752 }
753 recalcCols( col-1, 0 );
754}
755
756void KWTableFrameSet::resizeRow( unsigned int row, double y )
757{
758 kdDebug() << k_funcinfo << row << "," << y << endl;
759 double difference = m_rowPositions[row];
760 if ((row != 0) && (y - m_rowPositions[ row-1 ] < s_minFrameHeight))
761 m_rowPositions[ row ] = m_rowPositions[ row-1 ] + s_minFrameHeight;
762 else
763 if ((row != getRows()) && (m_rowPositions[ row + 1 ] - y < s_minFrameHeight))
764 m_rowPositions[row] = m_rowPositions[ row + 1 ] - s_minFrameHeight;
765 else
766 m_rowPositions[ row ] = y;
767 difference = m_rowPositions[row] - difference;
768
769 //move all rows under 'row'
770 if (row != 0)
771 for (unsigned int i=row+1; i<= getRows(); i++)
772 m_rowPositions[i] = m_rowPositions[i] + difference;
773
774 // move all cells under 'row'
775 for (TableIter cell(this); cell; ++cell) {
776 if ( cell->rowAfter() >= row ) {
777 position(cell);
778 }
779 }
780 recalcRows( 0, row-1 );
781}
782
783void KWTableFrameSet::resizeWidth( double width ) {
784 Q_ASSERT(width != 0);
785 Q_ASSERT(boundingRect().width() != 0);
786 kdDebug() << "bounding width before resize " << boundingRect().width() << endl;
787 double growth = width / boundingRect().width();
788
789 // since we move all the columns, we also move the 1st one,
790 // depending where it is on the page.
791 // just compensate by substracting that offset.
792 double moveOffset = m_colPositions[0] * growth - m_colPositions[0];
793
794 for (uint i=0; i<m_colPositions.count(); i++) {
795 m_colPositions[i] = m_colPositions[i] * growth - moveOffset;
796 }
797 finalize();
798 kdDebug() << "bounding width after resize" << boundingRect().width() << endl;
799 Q_ASSERT(boundingRect().width() - width < 0.01);
800}
801
802void KWTableFrameSet::setBoundingRect( KoRect rect, CellSize widthMode, CellSize heightMode ) {
803 // Column positions..
804 m_colPositions.clear();
805 unsigned int cols=0;
806 for (TableIter c(this); c; ++c)
807 cols = kMax(cols, c.current()->columnAfter());
808 double colWidth = rect.width() / cols;
809 if ( widthMode == TblAuto ) {
810 KWPage *page = pageManager()->page(rect);
811 rect.setLeft( page->leftMargin() );
812 colWidth = (page->width() - page->leftMargin() - page->rightMargin()) / cols;
813 }
814
815 for(unsigned int i=0; i <= cols;i++) {
816 m_colPositions.append(rect.x() + colWidth * i);
817 }
818
819 // Row positions..
820 m_rowPositions.clear();
821 m_pageBoundaries.clear();
822 double rowHeight = 0;
823 if( heightMode != TblAuto )
824 rowHeight = rect.height() / m_rows;
825 rowHeight=kMax(rowHeight, 22.0); // m_doc->getDefaultParagLayout()->getFormat().ptFontSize()) // TODO use table style font-size
826
827 for(unsigned int i=0; i <= m_rows;i++) {
828 m_rowPositions.append(rect.y() + rowHeight * i);
829 }
830
831 double oneMm = MM_TO_POINT( 1.0 );
832 for (TableIter cell(this); cell; ++cell) {
833 KWFrame *frame = cell->frame(0);
834 frame->setPaddingLeft( oneMm );
835 frame->setPaddingRight( oneMm );
836 frame->setPaddingTop( oneMm );
837 frame->setPaddingBottom( oneMm );
838 frame->setNewFrameBehavior( KWFrame::NoFollowup );
839 position(cell, true);
840 }
841}
842
843void KWTableFrameSet::position( Cell *theCell, bool setMinFrameHeight ) {
844 if(!theCell->frame(0)) { // sanity check.
845 kdDebug(32004) << "errorous table cell!! row:" << theCell->firstRow()
846 << ", col: " << theCell->firstColumn() << endl;
847 return;
848 }
849 double x = *m_colPositions.at(theCell->firstColumn());
850 double y = getPositionOfRow(theCell->firstRow());
851 double width = (*m_colPositions.at(theCell->columnAfter())) - x;
852 double height = getPositionOfRow(theCell->lastRow(), true) - y;
853
854#if 0
855 if(theCell->m_col==0) {
856 kdDebug(32004) << "row " << theCell->firstRow() << " has top: "
857 << y << ", and bottom: " << y + height << endl;
858 }
859#endif
860
861 // Now take the border sizes and make the cell smaller so it still fits inside the grid.
862 KWFrame *theFrame = theCell->frame(0);
863 x+=theCell->leftBorder();
864 width-=theCell->leftBorder();
865 width-=theCell->rightBorder();
866 y+=theCell->topBorder();
867 height-=theCell->topBorder();
868 height-=theCell->bottomBorder();
869
870 theFrame->setRect( x,y,width,height);
871 if( setMinFrameHeight )
872 theFrame->setMinimumFrameHeight(height);
873
874 if(!theCell->isVisible())
875 theCell->setVisible(true);
876}
877
878double KWTableFrameSet::getPositionOfRow( unsigned int row, bool bottom ) {
879 unsigned int adjustment=0;
880 TQValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
881 while(pageBound != m_pageBoundaries.end() && (*pageBound) <= row + adjustment) {
882 adjustment++;
883 pageBound++;
884 }
885 if(m_rowPositions.count() < row+adjustment+(bottom?1:0)) // Requested row does not exist.
886 return 0;
887 return m_rowPositions[row+adjustment+(bottom?1:0)];
888}
889
890void KWTableFrameSet::moveBy( double dx, double dy ) {
891 bool redraw=false;
892 kdDebug(32004) << "KWTableFrameSet(" << name() << ")::moveBy(" << dx<<","<<dy<<")\n";
893 //for(unsigned int i=0; i < m_rowPositions.count() ; kdDebug(32004) << "row " << i << ": " << m_rowPositions[i++] << endl);
894 if(!(dy > -0.001 && dy < 0.001)) {
895 redraw=true;
896 TQValueList<double>::iterator row = m_rowPositions.begin();
897 while(row != m_rowPositions.end()) {
898 (*row)= (*row)+dy;
899 row++;
900 }
901 }
902 if(!(dx > -0.001 && dx < 0.001)) {
903 redraw=true;
904 TQValueList<double>::iterator col = m_colPositions.begin();
905 while(col != m_colPositions.end()) {
906 (*col)= (*col)+dx;
907 col++;
908 }
909 }
910
911 if(redraw) {
912 for(TableIter cell(this);cell;++cell)
913 position(cell);
914 }
915}
916
917/* Delete all cells that are completely in this row. */
918void KWTableFrameSet::deleteRow( unsigned int row, RemovedRow &rr, bool _recalc)
919{
920 Q_ASSERT(row < m_rowArray.size());
921 const unsigned int rowspan=1;
922
923 double height= getPositionOfRow(row+rowspan-1,true) - getPositionOfRow(row);
924 TQValueList<double>::iterator tmp = m_rowPositions.at(row+rowspan);
925 tmp=m_rowPositions.erase(tmp);
926 while(tmp!=m_rowPositions.end()) {
927 (*tmp)= (*tmp)-height;
928 tmp++;
929 }
930
931 rr.m_index = row;
932 rr.m_rowHeight = height;
933 rr.m_row = m_rowArray[row];
934
935 // move/delete cells.
936 for ( TableIter cell(this); cell; ++cell ) {
937 if ( row >= cell->firstRow() && row < cell->rowAfter()) { // cell is indeed in row
938 if(cell->rowSpan() == 1) { // cell is wholly contained within row
939 m_frames.remove( cell->frame(0) );
940 } else { // make cell span rowspan less rows
941 cell->setRowSpan(cell->rowSpan()-rowspan);
942 position(cell);
943 }
944
945 } else if ( cell->firstRow() > row ) {
946 // move cell up
947 cell->setFirstRow( cell->firstRow() - rowspan );
948 position(cell);
949 }
950 }
951
952 removeRowVector(row);
953 m_rows -= rowspan;
954 m_rowArray.resize( m_rows );
955 validate();
956
957 if ( _recalc )
958 recalcRows( 0, row-1 );
959}
960
962{
963 uint row = rr.index();
964 Row *r = rr.row();
965 uint rlen = r->count();
966
967 // adjust cell positions & sizes
968 for(MarkedIterator cell(this); cell; ++cell) {
969
970 if ( cell->firstRow() < row && cell->lastRow() >= row ){ // cell is indeed in row
971 cell->setRowSpan(cell->rowSpan() + 1);
972 }
973 else if(r->m_cellArray[cell->firstColumn()] == cell.current()) {
974 cell->setRowSpan(cell->rowSpan() + 1);
975 }
976 else if ( cell->firstRow() >= row ) {
977 // move cell down
978 cell->setFirstRow( cell->firstRow() + 1);
979 }
980 }
981
982 // put back m_frames that were removed
983 for(uint i = 0; i < rlen; i++){
984 if( m_frames.findRef((*r)[i]->frame(0)) == -1 )
985 m_frames.append( (*r)[i]->frame(0) );
986 }
987
988 // adjust row positions (ignores page boundaries!)a
989 if(row == m_rows) { //reinserting at bottom of table
990 double d = m_rowPositions.last() + rr.height();
991 m_rowPositions.append(d);
992 }
993 else {
994 TQValueList<double>::iterator top = m_rowPositions.at(row);
995 TQValueList<double>::iterator i = m_rowPositions.at(row+1);
996 i = m_rowPositions.insert(i, *top + rr.height());
997 i++;
998 for(; i != m_rowPositions.end(); ++i) {
999 *i = *i+ rr.height();
1000 }
1001 }
1002
1003 // reinsert row into array
1004 m_rows++;
1005 insertRowVector(rr.index(), rr.takeRow());
1006
1007 // don't actually have to visit all the cells, this could be optimised
1008 for(TableIter i(this); i ; ++i)
1009 position(i.current());
1010
1011 validate();
1012}
1013
1014void KWTableFrameSet::insertNewRow( uint idx, bool recalc, bool _removeable)
1015{
1016
1017 (void) _removeable; // unused parameter
1018 unsigned int copyFromRow = idx==0?0:idx-1;
1019 if(idx==0)
1020 copyFromRow=1;
1021 Row *copyRow = m_rowArray[copyFromRow];
1022
1023 uint new_rows = m_rows + 1;
1024 // What height to use for the new row
1025 double height = getPositionOfRow(copyFromRow,true) - getPositionOfRow(copyFromRow);
1026
1027 // Calculate offset in TQValueList because of page breaks.
1028 unsigned int adjustment=0;
1029 unsigned int untilRow=m_rows;
1030 TQValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
1031 while(pageBound != m_pageBoundaries.end() && (*pageBound) <= idx) {
1032 // Find out how many pages we already had.
1033 adjustment++;
1034 pageBound++;
1035 }
1036
1037 // Move all rows down from newRow to bottom of page
1038 TQValueList<double>::iterator tmp = m_rowPositions.at(idx);
1039 double newPos = *tmp + height;
1040 tmp++;
1041 m_rowPositions.insert(tmp, newPos);
1042 for(unsigned int i=idx+adjustment+2; i < m_rowPositions.count(); i++) {
1043 double &rowPos = m_rowPositions[i];
1044 kdDebug(32004) << "adjusting " << rowPos << " -> " << rowPos + height << endl;
1045 rowPos = rowPos + height;
1046 if(*pageBound == i) {
1047 untilRow= *pageBound;
1048 break; // stop at pageBreak.
1049 }
1050 }
1051
1052 for ( MarkedIterator cells(this); cells; ++cells) {
1053 if ( cells->firstRow() >= idx ) { // move all cells beneath the new row.
1054 cells->setFirstRow(cells->firstRow()+1);
1055 }
1056 }
1057
1058 insertRowVector(idx, new Row);
1059
1060 unsigned int i = 0;
1061 while(i < getColumns()) {
1062
1063 if(idx != 0 && (idx != m_rows)) {
1064 Cell *c = cell(idx - 1, i);
1065 if( c == cell(idx + 1, i) ) {
1066 m_rowArray[idx]->addCell(c);
1067 c->setRowSpan(c->rowSpan() + 1);
1068 i += c->columnSpan();
1069 continue; // don't need to make a new cell
1070 }
1071 }
1072
1073 KWFrame *theFrame = new KWFrame(copyRow->m_cellArray[i]->frame(0));
1074 Cell *newCell=new Cell( this, idx, i, TQString() );
1075 newCell->setColumnSpan( cell(copyFromRow,i)->columnSpan() );
1076 addCell(newCell);
1077 newCell->addFrame( theFrame, false );
1078 position(newCell);
1079 i += newCell->columnSpan();
1080 }
1081
1082 // Position all changed cells.
1083
1084 m_rows = new_rows;
1085 validate();
1086 if ( recalc )
1087 finalize();
1088}
1089
1090void KWTableFrameSet::deleteColumn(uint col, RemovedColumn &rc)
1091{
1092 // keep these values in case we have to put it back
1093 if(!rc.m_initialized) {
1094 rc.m_index = col;
1095 rc.m_width = m_colPositions[col+1] - m_colPositions[col];
1096 }
1097
1098 // move the colomn positions
1099 TQValueList<double>::iterator tmp = m_colPositions.at(col+1);
1100 tmp = m_colPositions.erase(tmp);
1101 while(tmp != m_colPositions.end()) {
1102 (*tmp) = (*tmp) - rc.m_width;
1103 tmp++;
1104 }
1105
1106 // remove cells that are wholy in this column,
1107 // otherwise reduce rowspan. pointers to all cells
1108 // are kept in the RemovedColumn
1109 CheckedIter iter(this);
1110 for(uint i = 0; i < m_rows; ++i) {
1111 Cell *daCell = cell(i, col);
1112
1113 if(!rc.m_initialized) {
1114 rc.m_column.append(daCell);
1115 rc.m_removed.append(daCell->columnSpan() == 1);
1116 }
1117
1118 if(daCell->columnSpan() == 1) { // lets remove it
1119 if(daCell->firstRow() == i) {
1120 m_frames.remove( daCell->frame(0) );
1121 m_nr_cells--;
1122 }
1123 m_rowArray[i]->m_cellArray.insert(col, 0);
1124 }
1125 else { // make cell span 1 less column
1126 if(daCell->firstRow() == i) {
1127 daCell->setColumnSpan( daCell->columnSpan() - 1 );
1128 position(daCell);
1129 }
1130 }
1131 }
1132
1133 // adjust cells in a later column
1134 for(; iter; ++iter) {
1135 if (iter->firstColumn() > col ) {
1136 iter->setFirstColumn( iter->firstColumn() - 1);
1137 position(iter.current());
1138 }
1139 }
1140
1141 // move pointers in 2d array back one column to occupy
1142 // removed column
1143 for(uint i = 0; i < m_rows; i++) {
1144 for(uint j = col + 1; j < m_cols; j++)
1145 m_rowArray[i]->m_cellArray.insert(j-1, m_rowArray[i]->m_cellArray[j]);
1146 }
1147 m_cols--;
1148 rc.m_initialized = true;
1149
1150 validate();
1151 recalcCols( col, 0 );
1152 recalcRows( col, 0 );
1153}
1154
1155void KWTableFrameSet::reInsertColumn(RemovedColumn &rc)
1156{
1157 TQValueList<double>::iterator tmp = m_colPositions.at(rc.m_index);
1158
1159 tmp = m_colPositions.insert(tmp, *tmp);
1160 tmp++;
1161 while(tmp != m_colPositions.end()) {
1162 (*tmp) = (*tmp) + rc.m_width;
1163 tmp++;
1164 }
1165
1166 // if a cell starts after the column we are inserting, it
1167 // must be moved to the right, except if it is going to
1168 // occury the reinserted column also.
1169 for ( MarkedIterator cells(this); cells ; ++cells ) {
1170 if ( cells->firstColumn() >= rc.m_index &&
1171 (rc.m_column.at(cells->firstRow()) != cells.current())) {
1172
1173 cells->setFirstColumn(cells->firstColumn() + 1);
1174 }
1175 }
1176 insertEmptyColumn(rc.m_index);
1177 m_cols++;
1178
1179 for(uint i = 0; i < m_rows; ++i) {
1180 bool removed = rc.m_removed[i];
1181 Cell *daCell = rc.m_column.at(i);
1182 if(i == daCell->firstRow()) {
1183 if(removed) {
1184 daCell->setColumnSpan(1);
1185 m_frames.append(daCell->frame(0));
1186 m_nr_cells++;
1187 }
1188 else {
1189 daCell->setColumnSpan(daCell->columnSpan() + 1);
1190 }
1191 addCell(daCell);
1192 }
1193 }
1194
1195 validate();
1196 finalize();
1197}
1198
1199void KWTableFrameSet::insertNewColumn( uint idx, double width)
1200{
1201 TQValueList<double>::iterator tmp = m_colPositions.at(idx);
1202
1203 tmp = m_colPositions.insert(tmp, *tmp);
1204 tmp++;
1205 while(tmp!=m_colPositions.end()) {
1206 (*tmp)= (*tmp)+width;
1207 tmp++;
1208 }
1209
1210 for ( MarkedIterator cells(this); cells ; ++cells ) {
1211 if ( cells->firstColumn() >= idx) { // move all cells right of the new col.
1212 cells->setFirstColumn(cells->firstColumn() + 1);
1213 }
1214 }
1215 insertEmptyColumn(idx);
1216 m_cols++;
1217 uint copyCol = (idx == 0) ? 1 : idx - 1 ;
1218
1219 // make the new cells
1220 // note that the loop counter is mucked with in the loop!
1221 for( unsigned int i = 0; i < getRows(); i++ ) {
1222
1223 // can't break a cell in half, so if there is the same cell
1224 // on both sides of inserted column, it occupies the new
1225 // column as well
1226 if(idx != 0 && (idx != m_cols -1)) {
1227 Cell *c = cell(i, idx - 1);
1228 if( c == cell(i, idx + 1) ) {
1229// m_rowArray[i]->m_cellArray.insert(idx, c);
1230 c->setColumnSpan(c->columnSpan() + 1);
1231 addCell(c);
1232 i += c->rowSpan() - 1;
1233 continue; // don't need to make a new cell
1234 }
1235 }
1236
1237 Cell *newCell = new Cell( this, i, idx, TQString() );
1238 KWFrame *theFrame = new KWFrame(cell(i, copyCol)->frame(0));
1239 newCell->addFrame( theFrame, false );
1240 position(newCell);
1241 m_nr_cells++;
1242 }
1243 validate();
1244 finalize();
1245}
1246
1248{
1249// m_cells.setAutoDelete( false );
1250// m_cells.clear();
1251 m_nr_cells = 0;
1252
1253 m_active = false;
1254}
1255
1256void KWTableFrameSet::group()
1257{
1258// m_cells.setAutoDelete( true );
1259// m_cells.clear();
1260
1261 m_nr_cells = 0;
1262 m_active = true;
1263}
1264
1265KCommand *KWTableFrameSet::joinCells(unsigned int colBegin,unsigned int rowBegin, unsigned int colEnd,unsigned int rowEnd) {
1266 Cell *firstCell = cell(rowBegin, colBegin);
1267 // if just one cell selected for joining; exit.
1268 if(rowBegin == rowEnd && colBegin == colEnd || cell(rowBegin,colBegin) == cell(rowEnd,colEnd))
1269 return 0L;
1270 TQPtrList<KWFrameSet> listFrameSet;
1271 TQPtrList<KWFrame> listCopyFrame;
1272
1273 // do the actual merge.
1274 for(unsigned int i=colBegin; i<=colEnd;i++) {
1275 for(unsigned int j=rowBegin; j<=rowEnd;j++) {
1276 Cell *daCell = cell(j,i);
1277 if(daCell && daCell!=firstCell) {
1278 listFrameSet.append(daCell);
1279 KWFrame* frame = daCell->frame(0);
1280 Q_ASSERT(frame);
1281 if(! frame) continue; // see bug #132642
1282 listCopyFrame.append(frame->getCopy());
1283 daCell->deleteFrame(frame);
1284 }
1285 }
1286 }
1287
1288 Q_ASSERT(firstCell);
1289 // update firstcell properties to reflect the merge
1290 firstCell->setColumnSpan(colEnd-colBegin+1);
1291 firstCell->setRowSpan(rowEnd-rowBegin+1);
1292 addCell(firstCell);
1293 position(firstCell);
1294 validate();
1295
1296 m_doc->updateAllFrames(); // TODO: only fs->updateFrames() & m_doc->updateFramesOnTopOrBelow(pageNum)
1297 m_doc->repaintAllViews();
1298 return new KWJoinCellCommand( i18n("Join Cells"), this,colBegin,rowBegin, colEnd,rowEnd,listFrameSet,listCopyFrame);
1299}
1300
1301KCommand *KWTableFrameSet::splitCell(unsigned int intoRows, unsigned int intoCols, unsigned int col, unsigned int row, TQPtrList<KWFrameSet> listFrameSet, TQPtrList<KWFrame>listFrame) {
1302 if(intoRows < 1 || intoCols < 1)
1303 return 0L;
1304
1305 kdDebug(32004) << "KWTableFrameSet::splitCell" << endl;
1306 Cell *daCell=cell(row,col);
1307 int rowsDiff = intoRows - daCell->rowSpan();
1308 int colsDiff = ((int) intoCols) - daCell->columnSpan();
1309
1310 if(rowsDiff >0) {
1311 unsigned int adjustment=0;
1312 TQValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
1313 while(pageBound != m_pageBoundaries.end() && (*pageBound) <= row) {
1314 adjustment++;
1315 pageBound++;
1316 }
1317 double height = (m_rowPositions[row+adjustment+1] - m_rowPositions[row+adjustment])/intoRows;
1318
1319 TQValueList<double>::iterator iRow = m_rowPositions.at(adjustment+row);
1320 for (int i=0; i < rowsDiff; i++) {
1321 double newPos = *iRow + height;
1322 iRow++;
1323 iRow=m_rowPositions.insert(iRow, newPos);
1324 }
1325
1326 // insert more rows into m_rowArray
1327 for(int i = 0; i < rowsDiff; ++i) {
1328 insertRowVector(row+i+1, new Row);
1329 m_rows++;
1330 }
1331
1332 // m_rows += rowsDiff;
1333 //for(unsigned int i=0; i < m_rowPositions.count() ; ++i)
1334 // kdDebug(32004) << "row " << i << ": " << m_rowPositions[i] << endl);
1335 }
1336 if(colsDiff >0) {
1337 double width = (m_colPositions[col+1] - m_colPositions[col])/intoCols;
1338
1339 TQValueList<double>::iterator iCol = m_colPositions.at(col);
1340 for (int i=0; i < colsDiff; i++) {
1341 double newPos = *iCol + width;
1342 iCol++;
1343 iCol=m_colPositions.insert(iCol, newPos);
1344 }
1345
1346 for(int i = 0; i < colsDiff; i++) {
1347 insertEmptyColumn(col+i+1);
1348 m_cols++;
1349 }
1350 //for(unsigned int i=0; i < m_colPositions.count(); ++i)
1351 // kdDebug(32004) << "col " << i << ": " << m_colPositions[i] << endl);
1352 //m_cols += colsDiff;
1353 }
1354
1355 // adjust cellspan and rowspan on other cells.
1356 for (CheckedIter i(this); i ; ++i) {
1357 if(daCell == i) continue;
1358
1359 if(rowsDiff>0) {
1360 if(row >= i->firstRow()&& row < i->firstRow()+ i->rowSpan())
1361 i->setRowSpan(i->rowSpan() + rowsDiff);
1362 if(i->firstRow() > row) {
1363 i->setFirstRow(i->firstRow() + rowsDiff);
1364 // theCell->frame(0)->setTop(theCell->frame(0)->top()+extraHeight);
1365 }
1366 }
1367 if(colsDiff>0) {
1368 if(col >= i->firstColumn() && col < i->columnAfter())
1369 i->setColumnSpan(i->columnSpan() + colsDiff);
1370 if(i->firstColumn() > col)
1371 i->setFirstColumn(i->firstColumn() + colsDiff);
1372 }
1373 /*if(extraHeight != 0 && theCell->firstRow()== row) {
1374 theCell->frame(0)->setHeight(theCell->frame(0)->height()+extraHeight);
1375 } */
1376 if ( rowsDiff > 0 || colsDiff > 0 ) // something changed?
1377 addCell( i ); // update arrays
1378 }
1379
1380 int i=0;
1381 KWFrame *firstFrame = daCell->frame(0);
1382 // create new cells
1383 for (unsigned int y = 0; y < intoRows; y++) {
1384 for (unsigned int x = 0; x < intoCols; x++){
1385 if(x==0 && y==0)
1386 continue; // the orig cell takes this spot.
1387
1388 Cell *lastFrameSet=0L;
1389
1390 if(listFrameSet.isEmpty())
1391 lastFrameSet = new Cell( this, y + row, x + col );
1392 else
1393 lastFrameSet = static_cast<KWTableFrameSet::Cell*> (listFrameSet.at(i));
1394 lastFrameSet->setGroupManager(this);
1395
1396 KWFrame *theFrame=0L;
1397 if(listFrame.isEmpty())
1398 {
1399 theFrame=firstFrame->getCopy();
1400 theFrame->setRunAround( KWFrame::RA_NO );
1401 theFrame->setFrameBehavior(KWFrame::AutoExtendFrame);
1402 theFrame->setNewFrameBehavior(KWFrame::NoFollowup);
1403 lastFrameSet->addFrame( theFrame,false );
1404 }
1405 else
1406 lastFrameSet->addFrame( listFrame.at(i)->getCopy(),false );
1407 i++;
1408
1409 // if the orig cell spans more rows/cols than it is split into, make first col/row wider.
1410 if(rowsDiff <0 && y==0)
1411 lastFrameSet->setRowSpan(lastFrameSet->rowSpan() - rowsDiff);
1412 if(colsDiff <0 && x==0)
1413 lastFrameSet->setColumnSpan(lastFrameSet->columnSpan() - colsDiff);
1414
1415 addCell( lastFrameSet );
1416 position(lastFrameSet);
1417 }
1418 }
1419
1420 // set new row and col-span. Use intermediate ints otherwise we get strange results as the
1421 // intermediate result could be negative (which goes wrong with unsigned ints)
1422 int r = (daCell->rowSpan() +1) - intoRows;
1423 if(r < 1) r=1;
1424 daCell->setRowSpan(r);
1425
1426 int c = (daCell->columnSpan() + 1) - intoCols;
1427 if(c < 1) c=1;
1428 daCell->setColumnSpan(c);
1429
1430 position(daCell);
1431 addCell(daCell);
1432 validate();
1433
1434 finalize();
1435
1436 return new KWSplitCellCommand(i18n("Split Cells"),this,col,row,intoCols, intoRows);
1437}
1438
1439void KWTableFrameSet::viewFormatting( TQPainter &/*painter*/, int )
1440{
1441}
1442
1444{
1445 for(CheckedIter cells(this); cells; ++cells) {
1446 if(cells->columnSpan() == 0 || cells->rowSpan() == 0) {
1447 kdDebug(32004) << " KWTableFrameSet::validate(): zero dimension" << endl;
1448 kdDebug(32004) << cells->firstRow() << " " << cells->firstColumn() << " " << cells->rowSpan()
1449 << " " << cells->columnSpan() << endl;
1450 }
1451
1452 for(uint i = cells->firstRow(); i < cells->rowAfter(); ++i) {
1453
1454 for(uint j = cells->firstColumn(); j < cells->columnAfter(); ++j) {
1455 if( cell(i,j) != cells.current() ) {
1456
1457 TQString str = TQString("| 0x%1 ").arg( (unsigned long)cells.current(), 0, 16 );
1458 kdDebug(32004) << " KWTableFrameSet::validate() failed " << endl;
1459 kdDebug(32004) << "at row: "<< i << " col: "<< j << " cell: "<< str << endl;
1460 kdDebug(32004) << cells->firstRow() << " " << cells->firstColumn() << " " << cells->rowSpan()
1461 << " " << cells->columnSpan() << endl;
1462 //printArrayDebug();
1463 }
1464 }
1465 }
1466 }
1467}
1468
1469void KWTableFrameSet::createEmptyRegion( const TQRect & crect, TQRegion & emptyRegion, KWViewMode *viewMode )
1470{
1471 // Avoid iterating over all cells if we are out of view
1472 if ( !viewMode->normalToView( m_doc->zoomRect( boundingRect() ) ).intersects( crect ) )
1473 return;
1474
1475 TQRect outerRect( viewMode->normalToView( m_doc->zoomRect( boundingRect() )));
1476 outerRect &= crect;
1477 if ( !outerRect.isEmpty() )
1478 emptyRegion = emptyRegion.subtract( outerRect );
1479
1480 TQPtrListIterator<KWFrame> frameIt = frameIterator();
1481 for ( ; frameIt.current(); ++frameIt )
1482 {
1483 TQRect outerRect( viewMode->normalToView( frameIt.current()->outerRect(viewMode) ) );
1484 //kdDebug(32004) << "KWTableFrameSet::createEmptyRegion outerRect=" << DEBUGRECT( outerRect )
1485 // << " crect=" << DEBUGRECT( crect ) << endl;
1486 outerRect &= crect;
1487 if ( !outerRect.isEmpty() )
1488 emptyRegion = emptyRegion.subtract( outerRect );
1489 }
1490}
1491
1492void KWTableFrameSet::drawBorders( TQPainter& painter, const TQRect &crect, KWViewMode *viewMode ) {
1493
1494 /* Draw the borders on top of the lines stores in the m_rowPositions and m_colPositions arrays.
1495 * check the relevant cells for borders and thus line thickness.
1496 * We move the outer lines (on row==0 and col==0 plus on col=getColumns() etc) a bit so they will stay
1497 * inside the boundary of the table!
1498 */
1499 painter.save();
1500 TQPen previewLinePen( TQApplication::palette().color( TQPalette::Active, TQColorGroup::Mid ) );
1501 TQColor defaultBorderColor = KoTextFormat::defaultTextColor( &painter );
1502 const int minborder = 1;
1503 bool drawPreviewLines = viewMode && viewMode->drawFrameBorders();
1504
1505 // *** draw horizontal lines *** //
1506 unsigned int row=0;
1507 TQValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
1508 for (unsigned int i=0 ; i < m_rowPositions.count() ; i++) {
1509 //kdDebug(32004) << "Horizontal line code. i: " << i << endl;
1510 bool bottom=false;
1511 if( (pageBound!=m_pageBoundaries.end() && (*pageBound) == row)
1512 || i == m_rowPositions.count()-1)
1513 bottom=true; // at end of page or end of table draw bottom border of cell.
1514
1515 const KoBorder *border=0;
1516 double startPos =0;
1517 for(unsigned int col=0; col <= getColumns();) {
1518 //kdDebug(32004) << "bottom=" << bottom << " row=" << row << " col=" << col << endl;
1519 Cell *daCell = col < getColumns() ? cell(bottom?row-1:row, col) : 0;
1520 //if(daCell) kdDebug(32004) << "cell (" << daCell->firstRow()<< "," << daCell->firstColumn() << ")" << endl;
1521 //else kdDebug(32004) << "cell: " << daCell << endl;
1522
1523 if(daCell && daCell->firstRow() != (bottom?row-1:row))
1524 daCell=0;
1525
1526 if(startPos!=0 && (!daCell || col == getColumns() || (
1527 bottom && daCell->frame(0)->bottomBorder()!=*border ||
1528 !bottom && daCell->frame(0)->topBorder()!=*border
1529 ))) {
1530 if(border->width() > 0 || drawPreviewLines) {
1531 double y = m_rowPositions[i];
1532 if(row==0)
1533 y+=border->width() / 2; // move slightly down.
1534 else if (row == getRows())
1535 y-=border->width() / 2; // move slightly up.
1536 int ypix = m_doc->zoomItY(y);
1537 double offset=0.0;
1538 if(border->width() > 0 && col!=getColumns()) { // offset border when not at right most cell.
1539 if(daCell) offset=daCell->leftBorder();
1540 if ( row > 0 ) {
1541 Cell *c = cell(row-1, col);
1542 if(c) offset=kMax(offset, c->leftBorder());
1543 }
1544 }
1545 double x = m_colPositions[col] + offset;
1546 TQPoint topLeft = viewMode->normalToView(TQPoint(m_doc->zoomItX(startPos), ypix));
1547 TQPoint bottomRight = viewMode->normalToView(TQPoint(m_doc->zoomItX(x), ypix));
1548 TQRect line = TQRect(topLeft, bottomRight);
1549 if(crect.intersects( line )) {
1550 //if(border->width() <= 0) kdDebug(32004) << "preview line" << endl;
1551 if(border->width() <= 0)
1552 painter.setPen( previewLinePen );
1553 else {
1554 int borderWidth = KoBorder::zoomWidthY( border->width(), m_doc, minborder );
1555 painter.setPen( KoBorder::borderPen( *border, borderWidth, defaultBorderColor ) );
1556 }
1557 //kdDebug(32004) << "Paint: painter.drawHorizontalLine(" << line.left() << "," << line.top() << "," << line.right() << "," << line.bottom() << ")\n";
1558 painter.drawLine( line.left(), line.top(), line.right(), line.bottom());
1559 }
1560 }
1561 // reset startPos
1562 startPos = 0;
1563 }
1564 if(daCell && startPos==0) {
1565 if(bottom)
1566 border=&(daCell->frame(0)->bottomBorder());
1567 else
1568 border=&(daCell->frame(0)->topBorder());
1569
1570 if(col==0) // left most cell
1571 startPos = m_colPositions[col];
1572 else {
1573 double offset=0.0;
1574 if(border->width() > 0) { // move line to the left a bit to compensate for the left border
1575 if(daCell) offset=daCell->leftBorder();
1576 if ( row > 0 ) {
1577 Cell *c = cell(row-1, col);
1578 if(c) offset=kMax(offset, c->leftBorder());
1579 }
1580 }
1581 startPos = m_colPositions[col] - offset;
1582 }
1583 }
1584 col += daCell ? daCell->columnSpan() : 1;
1585 }
1586 if(pageBound!=m_pageBoundaries.end() && (*pageBound) == row)
1587 pageBound++;
1588 else
1589 row++;
1590 }
1591
1592 // *** draw vertical lines *** //
1593 for (unsigned int col=0 ; col < m_colPositions.count(); col++) {
1594 //kdDebug(32004) << "Vertical line code. col: " << col << endl;
1595 bool right = false;
1596 if(col == m_colPositions.count()-1)
1597 right = true; // draw right border of cell.
1598 int cellColumn = right?col-1:col; // the column we'll be looking for in the loop below
1599 Q_ASSERT( cellColumn >= 0 );
1600
1601 const KoBorder *border = 0;
1602 int startRow = -1;
1603 for(unsigned int row=0; row <= getRows();) {
1604 //kdDebug(32004) << "row=" << row << " cellColumn=" << cellColumn << endl;
1605 Cell *daCell = row < getRows() ? cell(row, cellColumn) : 0;
1606
1607 //kdDebug(32004) << "Drawing vert. Line for cell row: " << row << " col: " << cellColumn << endl;
1608 if(daCell && daCell->firstColumn() != (uint)cellColumn)
1609 daCell=0;
1610
1611#if 0
1612 kdDebug() << "Condition: startRow:" << (startRow!=-1) << endl;
1613 if ( startRow != -1 ) {
1614 Q_ASSERT( border );
1615 kdDebug() << "Other conditions: cell:" << !daCell << endl;
1616 kdDebug() << " or last row:" << ( row == ( int )getRows() ) << endl;
1617 if ( daCell )
1618 kdDebug() << "Different border:" <<
1619 ( ( right && daCell->frame(0)->rightBorder() != *border) ||
1620 ( !right && daCell->frame(0)->leftBorder() != *border) )
1621 << endl;
1622 }
1623#endif
1624
1625 // be sure that the right border of the table is drawn even for joined cells
1626 if ( !daCell && startRow == -1 && cellColumn == ((int)m_colPositions.count()-2 ) && right )
1627 {
1628 // find the joined cell
1629 int col = cellColumn;
1630 while ( !daCell && col>0 )
1631 {
1632 col--;
1633 daCell = cell(row, col);
1634 }
1635 if ( daCell && daCell->isJoinedCell() && ( (int)daCell->columnSpan() + col -1 ) == cellColumn )
1636 {
1637 border = &(daCell->frame(0)->rightBorder());
1638 startRow = row;
1639 }
1640 else
1641 daCell = 0;
1642 }
1643
1644 // Draw when something changed (different kind of border) or we're at the end
1645 // This code could be rewritten in a more TQRT-like way
1646 // (iterate and compare with next, instead of the startRow/cell/border hack...)
1647 if(startRow != -1 &&
1648 (!daCell || row == getRows() ||
1649 ( right && daCell->frame(0)->rightBorder() != *border) ||
1650 ( !right && daCell->frame(0)->leftBorder() != *border) )
1651 ) {
1652 if(border->width() > 0 || drawPreviewLines) {
1653 double x = m_colPositions[col];
1654 if(col==0) {
1655 x+=border->width() / 2;
1656 } else if(col==getColumns()) {
1657 x-=border->width() / 2;
1658 }
1659 int xpix = m_doc->zoomItX(x);
1660 TQValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
1661 unsigned int topRow=startRow;
1662 //kdDebug(32004) << "Drawing from topRow=" << topRow << endl;
1663 do { // draw minimum of one line per page.
1664 while( pageBound != m_pageBoundaries.end() && *(pageBound) < topRow )
1665 pageBound++;
1666
1667 unsigned int bottomRow;
1668 if(pageBound == m_pageBoundaries.end())
1669 bottomRow = m_rowPositions.count()-1;
1670 else
1671 bottomRow = *(pageBound++);
1672
1673 //kdDebug(32004) << "from: " << topRow << " to: " << kMin((uint)row, bottomRow) << endl;
1674 //kdDebug(32004) << "from: " << m_rowPositions[topRow] << " to: " << m_rowPositions[kMin((uint)row, bottomRow)] << endl;
1675 double offset=0.0;
1676 if(border->width() > 0) {
1677 //kdDebug(32004) << "looking at topRow=" << topRow << " col=" << col << endl;
1678 Cell *c=cell(topRow,col);
1679 if(c) offset=c->topBorder();
1680 if ( col > 0 ) {
1681 c=cell(topRow,col-1);
1682 if(c) offset=kMax(offset,c->topBorder());
1683 }
1684 if(topRow==0) offset=0.0;
1685 }
1686 double top=m_rowPositions[topRow]-offset;
1687
1688 unsigned int toRow=kMin((uint)row,bottomRow);
1689 offset=0.0;
1690 if(border->width() > 0 && toRow!=bottomRow) {
1691 if(daCell) offset=daCell->topBorder();
1692 Cell *c=cell(toRow,col-1);
1693 if(c) offset=kMax(offset,c->topBorder());
1694 }
1695 double bottom=m_rowPositions[toRow] + offset;
1696
1697 TQPoint topLeft = viewMode->normalToView(TQPoint(xpix, m_doc->zoomItY(top)));
1698 TQPoint bottomRight = viewMode->normalToView(TQPoint(xpix, m_doc->zoomItY(bottom)));
1699 TQRect line = TQRect(topLeft, bottomRight);
1700 if(crect.intersects( line )) {
1701 if(border->width() <= 0)
1702 painter.setPen( previewLinePen );
1703 else {
1704 int borderWidth = KoBorder::zoomWidthX( border->width(), m_doc, minborder );
1705 painter.setPen(KoBorder::borderPen( *border, borderWidth, defaultBorderColor ));
1706 }
1707 //kdDebug(32004) << "drawBorders(): painter.drawVerticalLine(" << line.left() << "," << line.top() << "," << line.right() << "," << line.bottom() << ")\n";
1708 painter.drawLine( line.left(), line.top(), line.right(), line.bottom());
1709 }
1710
1711 topRow=bottomRow+1;
1712 } while(topRow < (uint)row && topRow != m_rowPositions.count());
1713 } // end "if border to be drawn"
1714
1715 // reset startRow
1716 startRow = -1;
1717 }
1718
1719 if(daCell && startRow == -1) {
1720 startRow = row;
1721 if(right)
1722 border = &(daCell->frame(0)->rightBorder());
1723 else
1724 border = &(daCell->frame(0)->leftBorder());
1725 //kdDebug(32004) << "startRow set to " << row << endl;
1726 }
1727 row += daCell ? daCell->rowSpan() : 1;
1728 //kdDebug(32004) << "End of loop, row=" << row << endl;
1729 }
1730 }
1731
1732#if 0
1733 if(drawPreviewLines) {
1734 TQPen minsizeLinePen( red );
1735 painter.setPen( minsizeLinePen );
1736 for ( unsigned int i = 0; i < m_cells.count(); i++ ) {
1737 Cell *daCell = m_cells.at( i );
1738 double y = daCell->frame(0)->top() + daCell->frame(0)->minimumFrameHeight() + 1.5;
1739 if(y >= daCell->frame(0)->bottom()) continue;
1740 int ypix=m_doc->zoomItY(y);
1741 TQPoint topLeft = viewMode->normalToView(TQPoint(m_doc->zoomItX(daCell->frame(0)->left()), ypix));
1742 TQPoint bottomRight = viewMode->normalToView(TQPoint(m_doc->zoomItX(daCell->frame(0)->right()), ypix));
1743 TQRect line = TQRect(topLeft, bottomRight);
1744 if(crect.intersects( line )) {
1745 painter.drawLine( line.left(), line.top(), line.right(), line.bottom());
1746 }
1747 }
1748 }
1749#endif
1750
1751 painter.restore();
1752}
1753
1754void KWTableFrameSet::drawContents( TQPainter * painter, const TQRect & crect,
1755 const TQColorGroup & cg, bool onlyChanged, bool resetChanged,
1756 KWFrameSetEdit * edit, KWViewMode * viewMode,
1757 KWFrameViewManager *fvm )
1758{
1759 for (TableIter cells(this) ; cells ; ++cells)
1760 {
1761 if (edit)
1762 {
1763 KWTableFrameSetEdit * tableEdit = static_cast<KWTableFrameSetEdit *>(edit);
1764 if ( tableEdit->currentCell() && ((Cell*) cells) == tableEdit->currentCell()->frameSet() )
1765 {
1766 cells->drawContents( painter, crect, cg, onlyChanged, resetChanged, tableEdit->currentCell(), viewMode, fvm );
1767 continue;
1768 }
1769 }
1770 cells->drawContents( painter, crect, cg, onlyChanged, resetChanged, 0L, viewMode, fvm );
1771 }
1772 drawBorders( *painter, crect, viewMode );
1773 //kdDebug(32004) << "drawContents()" << endl;
1774}
1775
1776// Called by KWAnchor for inline tables
1777// TODO: for non-inline ones we need a text-box around us...
1778// Well, even for inline-as-char ones.... Currently being debated with OASIS.
1779void KWTableFrameSet::saveOasis( KoXmlWriter& writer, KoSavingContext& context, bool ) const
1780{
1781 writer.startElement( "table:table" );
1782 writer.addAttribute( "table:name", name() );
1783 KoGenStyle tableStyle( KWDocument::STYLE_TABLE, "table" );
1784 tableStyle.addProperty( "table:align", "margins" );
1785 tableStyle.addPropertyPt( "style:width", m_colPositions.last()-m_colPositions[0] );
1786 const TQString tableStyleName = context.mainStyles().lookup( tableStyle, "table" );
1787 writer.addAttribute( "table:style-name", tableStyleName );
1788
1789 // ### to minimize the XML, we could use table:number-columns-repeated here
1790 // when a number of consecutive columns have the exact same style.
1791 for ( uint colNr = 0; colNr < getColumns(); ++colNr )
1792 {
1793 writer.startElement( "table:table-column" );
1794 KoGenStyle columnStyle( KWDocument::STYLE_TABLE_COLUMN, "table-column" );
1795 columnStyle.addPropertyPt( "style:column-width", m_colPositions[colNr+1] - m_colPositions[colNr] );
1796 const TQString colStyleName = context.mainStyles().lookup( columnStyle, "col" );
1797 writer.addAttribute( "table:style-name", colStyleName );
1798 writer.endElement(); // table:table-column
1799 }
1800
1801 // TODO table-header-rows once supported
1802
1803 for ( uint row = 0; row < getRows(); ++row )
1804 {
1805 writer.startElement( "table:table-row" );
1806
1807 KoGenStyle rowStyle( KWDocument::STYLE_TABLE_ROW, "table-row" );
1808 rowStyle.addPropertyPt( "table:row-height", m_rowPositions[row+1] - m_rowPositions[row] );
1809 // TODO is min-row-height or use-optimal-row-height necessary?
1810 const TQString rowStyleName = context.mainStyles().lookup( rowStyle, "row" );
1811 writer.addAttribute( "table:style-name", rowStyleName );
1812
1813 for ( uint col = 0; col < getColumns(); ++col )
1814 {
1815 Cell* daCell = cell(row, col);
1816 Q_ASSERT( daCell );
1817 if ( !daCell )
1818 continue;
1819
1820 if ( daCell->isFirstGridPosnFast( row, col ) )
1821 {
1822 writer.startElement( "table:table-cell" );
1823
1824 // Style: background, border, padding.
1825 KoGenStyle cellStyle( KWDocument::STYLE_TABLE_CELL_AUTO, "table-cell" );
1826 daCell->frame( 0 )->saveBorderProperties( cellStyle );
1827 const TQString colStyleName = context.mainStyles().lookup( cellStyle, "cell" );
1828 writer.addAttribute( "table:style-name", colStyleName );
1829
1830 // Attributes
1831 if ( daCell->columnSpan() > 1 )
1832 writer.addAttribute( "table:number-columns-spanned", daCell->columnSpan() );
1833 if ( daCell->rowSpan() > 1 )
1834 writer.addAttribute( "table:number-row-spanned", daCell->rowSpan() );
1835
1836 // Content
1837 daCell->saveOasisContent( writer, context );
1838
1839 writer.endElement(); // table:table-cell
1840 }
1841 else
1842 {
1843 // Empty element for the covered cell
1844 writer.startElement( "table:covered-table-cell" );
1845 writer.endElement();
1846 }
1847 }
1848 writer.endElement(); // table:table-row
1849 }
1850
1851 writer.endElement(); // table:table
1852}
1853
1854void KWTableFrameSet::loadOasis( const TQDomElement& tableTag, KoOasisContext& context )
1855{
1856 // Left position of each column. The last one defined is the right position of the last cell/column.
1857 TQMemArray<double> columnLefts(4);
1858 uint maxColumns = columnLefts.size() - 1;
1859
1860 uint col = 0;
1861 columnLefts[0] = 0.0; // Initialize left of first cell
1862 TQDomElement elem;
1863 forEachElement( elem, tableTag )
1864 {
1865 if ( elem.localName() == "table-column" && elem.namespaceURI() == KoXmlNS::table )
1866 {
1867 uint repeat = elem.attributeNS( KoXmlNS::table, "number-columns-repeated", "1").toUInt(); // Default 1 time
1868 if (!repeat)
1869 repeat=1; // At least one column defined!
1870 KoStyleStack& styleStack = context.styleStack();
1871 styleStack.setTypeProperties( "table-column" );
1872 styleStack.save();
1873 context.fillStyleStack( elem, KoXmlNS::table, "style-name", "table-column" );
1874
1875 TQString strWidth = styleStack.attributeNS( KoXmlNS::style, "column-width" );
1876 double width = KoUnit::parseValue( strWidth );
1877
1878 if ( width < 1.0 ) // Something is wrong with the width
1879 {
1880 kdWarning(32004) << "Table column width ridiculous, assuming 1 inch!" << endl;
1881 width = 72.0;
1882 }
1883 else
1884 kdDebug(32004) << "- style width " << width << endl;
1885
1886 for ( uint j = 0; j < repeat; ++j )
1887 {
1888 ++col;
1889 if ( col >= maxColumns )
1890 {
1891 // We need more columns
1892 maxColumns += 4;
1893 columnLefts.resize( maxColumns+1, TQGArray::SpeedOptim );
1894 }
1895 columnLefts[col] = width + columnLefts[col-1];
1896 kdDebug(32004) << "Cell column " << col-1 << " left " << columnLefts[col-1] << " right " << columnLefts[col] << endl;
1897 }
1898 styleStack.restore();
1899 }
1900 }
1901
1902 uint row = 0;
1903 uint column = 0;
1904 parseInsideOfTable( tableTag, context, columnLefts, row, column, 0 );
1905}
1906
1907void KWTableFrameSet::parseInsideOfTable( const TQDomElement& parent, KoOasisContext& context,
1908 const TQMemArray<double> & columnLefts, uint& row, uint& column,
1909 double currentRowHeight )
1910{
1911 kdDebug(32004) << "parseInsideOfTable" << endl;
1912 KoStyleStack& styleStack = context.styleStack();
1913
1914 TQDomElement e;
1915 forEachElement( e, parent )
1916 {
1917 const TQString localName = e.localName();
1918 const TQString ns = e.namespaceURI();
1919 if ( ns != KoXmlNS::table ) {
1920 kdWarning(32004) << "Skipping element " << e.tagName() << " (in parseInsideOfTable)" << endl;
1921 continue;
1922 }
1923
1924 styleStack.save();
1925 if ( localName == "table-cell" )
1926 {
1927 loadOasisCell( e, context, columnLefts, row, column, currentRowHeight );
1928 ++column;
1929 }
1930 else if ( localName == "covered-table-cell" )
1931 {
1932 ++column;
1933 }
1934 else if ( localName == "table-row" )
1935 {
1936 context.fillStyleStack( e, KoXmlNS::table, "style-name", "table-row" );
1937 context.styleStack().setTypeProperties( "table-row" );
1938
1939 // Load row height in case it was set - note that it might not be set (e.g. OOo)
1940 double rowHeight = styleStack.attributeNS( KoXmlNS::table, "row-height" ).toDouble();
1941 column = 0;
1942 parseInsideOfTable( e, context, columnLefts, row, column, rowHeight );
1943 ++row;
1944 }
1945 else if ( localName == "table-header-rows" ) // ###TODO
1946 {
1947 // TODO: do we need to fillStyleStack?
1948 parseInsideOfTable( e, context, columnLefts, row, column, currentRowHeight );
1949 }
1950 else if ( localName == "table-column" )
1951 {
1952 // Already treated in loadOasis, we do not need to do anything here!
1953 }
1954 // TODO sub-table [ add to stack and expand at end of table loading ]
1955 else
1956 {
1957 kdWarning(32004) << "Skipping element " << localName << " (in parseInsideOfTable)" << endl;
1958 }
1959
1960 styleStack.restore();
1961 }
1962}
1963
1964void KWTableFrameSet::loadOasisCell( const TQDomElement& element, KoOasisContext& context,
1965 const TQMemArray<double> & columnLefts, uint row, uint column,
1966 double currentRowHeight )
1967{
1968 //kdDebug(32004) << k_funcinfo << element.localName() << " " << row << "," << column << endl;
1969
1970 KoStyleStack& styleStack = context.styleStack();
1971 uint rowSpan = element.attributeNS( KoXmlNS::table, "number-rows-spanned", TQString() ).toUInt();
1972 if ( rowSpan == 0 )
1973 rowSpan = 1;
1974 uint colSpan = element.attributeNS( KoXmlNS::table, "number-columns-spanned", TQString() ).toUInt();
1975 if ( colSpan == 0 )
1976 colSpan = 1;
1977
1978 // m_rowPositions / m_colPositions could be TQMemArrays, or TQValueVectors...
1979 while(m_rowPositions.count() <= row + rowSpan + m_pageBoundaries.count()) {
1980 m_rowPositions.append(0);
1981 }
1982 while(m_colPositions.count() <= column + colSpan) {
1983 m_colPositions.append(0);
1984 }
1985
1986 Cell *daCell = new Cell( this, row, column, TQString() /*unused*/ );
1987
1988 daCell->setRowSpan( rowSpan );
1989 daCell->setColumnSpan( colSpan );
1990 addCell( daCell ); // rowSpan/colSpan have changed -> update array
1991
1992 double width = columnLefts[ TQMIN( column+colSpan, columnLefts.size()-1 ) ] - columnLefts[column];
1993 double height = currentRowHeight > 0 ? currentRowHeight : 20;
1994 KWFrame* frame = new KWFrame( daCell, columnLefts[column], 0, width, height );
1995 if ( currentRowHeight > 0 )
1996 frame->setMinimumFrameHeight( height ); // ensure that text formatting won't resize it down
1997 frame->setRunAround( KWFrame::RA_NO );
1998 frame->setFrameBehavior( KWFrame::AutoExtendFrame );
1999 frame->setNewFrameBehavior( KWFrame::NoFollowup );
2000 daCell->addFrame( frame, false );
2001
2002 context.fillStyleStack( element, KoXmlNS::table, "style-name", "table-cell" );
2003 styleStack.setTypeProperties( "table-cell" );
2004
2005 daCell->frame( 0 )->loadBorderProperties( styleStack );
2006
2007 daCell->loadOasisContent( element, context );
2008 afterLoadingCell( daCell );
2009}
2010
2011// Old XML
2012TQDomElement KWTableFrameSet::save( TQDomElement &parentElem, bool saveFrames ) {
2013 // When saving to a file, we don't have anything specific to the frameset to save.
2014 // Save the cells only.
2015 for (TableIter cells(this) ; cells ; ++cells)
2016 cells->save(parentElem, saveFrames);
2017 return TQDomElement(); // No englobing element for tables...
2018}
2019
2020// Old XML
2021TQDomElement KWTableFrameSet::toXML( TQDomElement &parentElem, bool saveFrames )
2022{
2023 TQDomElement framesetElem = parentElem.ownerDocument().createElement( "FRAMESET" );
2024 parentElem.appendChild( framesetElem );
2025 KWFrameSet::saveCommon( framesetElem, false ); // Save the frameset attributes
2026 // Save the cells
2027 save( framesetElem, saveFrames );
2028 return framesetElem;
2029}
2030
2031// Old XML
2032void KWTableFrameSet::fromXML( TQDomElement &framesetElem, bool loadFrames, bool useNames )
2033{
2034 KWFrameSet::load( framesetElem, false ); // Load the frameset attributes
2035 // Load the cells
2036 TQDomElement cellElem = framesetElem.firstChild().toElement();
2037 for ( ; !cellElem.isNull() ; cellElem = cellElem.nextSibling().toElement() )
2038 {
2039 if ( cellElem.tagName() == "FRAMESET" )
2040 loadCell( cellElem, loadFrames, useNames );
2041 }
2042}
2043
2044// Old XML
2045KWTableFrameSet::Cell* KWTableFrameSet::loadCell( TQDomElement &framesetElem, bool loadFrames, bool useNames )
2046{
2047 int _row = KWDocument::getAttribute( framesetElem, "row", 0 );
2048 if(_row <0) _row =0;
2049 unsigned int row=_row;
2050 int _col = KWDocument::getAttribute( framesetElem, "col", 0 );
2051 if(_col <0) _col =0;
2052 int _rows = KWDocument::getAttribute( framesetElem, "rows", 1 );
2053 if(_rows <0) _rows = 1;
2054 int _cols = KWDocument::getAttribute( framesetElem, "cols", 1 );
2055 if(_cols <0) _cols = 1;
2056
2057 // m_rowPositions / m_colPositions could be TQMemArrays, or TQValueVectors...
2058 while(m_rowPositions.count() <= static_cast<unsigned int>(row + _rows + m_pageBoundaries.count())) {
2059 m_rowPositions.append(0);
2060 }
2061 while(m_colPositions.count() <= static_cast<unsigned int>(_col + _cols)) {
2062 m_colPositions.append(0);
2063 }
2064
2065 Cell *daCell = new Cell( this, row, _col, TQString() /*unused*/ );
2066 TQString autoName = daCell->name();
2067 //kdDebug(32004) << "KWTableFrameSet::loadCell autoName=" << autoName << endl;
2068 daCell->load( framesetElem, loadFrames );
2069 daCell->setRowSpan(_rows);
2070 daCell->setColumnSpan(_cols);
2071 addCell( daCell ); // rowSpan/colSpan have changed -> update array
2072 afterLoadingCell( daCell );
2073 if ( !useNames )
2074 daCell->setName( autoName );
2075 return daCell;
2076}
2077
2078// Shared between old xml and oasis
2079void KWTableFrameSet::afterLoadingCell( Cell* daCell )
2080{
2081 uint row = daCell->firstRow();
2082 uint col = daCell->firstColumn();
2083 uint rowSpan = daCell->rowSpan();
2084 uint colSpan = daCell->columnSpan();
2085 if(m_pageBoundaries.count() > 0) {
2086 unsigned int adjustment=0;
2087 TQValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
2088 while(pageBound != m_pageBoundaries.end() && (*pageBound) <= row + adjustment) {
2089 adjustment++;
2090 pageBound++;
2091 }
2092 row+=adjustment;
2093 }
2094
2095 kdDebug(32004) << "loading cell (" << row << "," << col << ")\n";
2096 if(daCell->frame(0)) {
2097 daCell->frame(0)->setMinimumFrameHeight(daCell->frame(0)->height()); // TODO run the formatter over the text here
2098 TQValueList<double>::iterator tmp = m_colPositions.at(col);
2099 if(*tmp == 0) (*tmp) = daCell->frame(0)->left();
2100 else (*tmp) = (daCell->frame(0)->left() + *tmp) / 2;
2101
2102 tmp = m_colPositions.at(col+colSpan);
2103 if(*tmp == 0) (*tmp) = daCell->frame(0)->right();
2104 else (*tmp) = (daCell->frame(0)->right() + *tmp) / 2;
2105
2106 tmp = m_rowPositions.at(row);
2107 if(*tmp == 0)
2108 (*tmp) = daCell->frame(0)->top();
2109 else {
2110 if (static_cast<int>(*tmp/m_doc->pageLayout().ptHeight) < static_cast<int>(daCell->frame(0)->top()/m_doc->pageLayout().ptHeight)) {
2111 kdDebug(32004) << "This cell is on a new page" << endl;
2112 TQValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
2113 while(pageBound != m_pageBoundaries.end() && (*pageBound) < row) ++pageBound;
2114 if(*pageBound!=row) {
2115 m_pageBoundaries.insert(pageBound,row++);
2116 ++tmp;
2117 m_rowPositions.insert(tmp,daCell->frame(0)->top());
2118 }
2119 } else
2120 (*tmp) = (daCell->frame(0)->top() + *tmp) / 2;
2121 }
2122
2123 tmp = m_rowPositions.at( row + rowSpan );
2124 if(*tmp == 0)
2125 (*tmp) = daCell->frame(0)->bottom();
2126 else { // untested...
2127 if (static_cast<int>(*tmp/m_doc->pageLayout().ptHeight) > static_cast<int>(daCell->frame(0)->top()/m_doc->pageLayout().ptHeight)) {
2128 kdDebug(32004) << "next cell is on a new page" << endl;
2129 TQValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
2130 while(pageBound != m_pageBoundaries.end() && (*pageBound) < row) ++pageBound;
2131 if(*pageBound!=row) {
2132 m_pageBoundaries.insert(pageBound,row++);
2133 m_rowPositions.insert(tmp,daCell->frame(0)->bottom());
2134 }
2135 } else
2136 (*tmp) = (daCell->frame(0)->bottom() + *tmp) / 2;
2137 }
2138 }
2139
2140 if ( m_rowPositions.count() != m_rows + 1 ) {
2141 kdDebug() << name() << " loadCell: m_rowPositions=" << m_rowPositions.count() << " m_rows= " << m_rows << endl;
2142 }
2143}
2144
2146{
2147 int paragraphs = 0;
2148 for (TableIter cells(this) ; cells ; ++cells)
2149 paragraphs += cells->paragraphs();
2150 return paragraphs;
2151}
2152
2153int KWTableFrameSet::paragraphsSelected()
2154{
2155 int paragraphs = 0;
2156 for (TableIter cells(this) ; cells ; ++cells)
2157 paragraphs += cells->paragraphsSelected();
2158 return paragraphs;
2159}
2160
2161bool KWTableFrameSet::statistics( TQProgressDialog *progress, ulong & charsWithSpace, ulong & charsWithoutSpace, ulong & words,
2162 ulong & sentences, ulong & syllables, ulong & lines, bool selected )
2163{
2164 for (TableIter cells(this) ; cells ; ++cells)
2165 if( ! cells->statistics( progress, charsWithSpace, charsWithoutSpace, words, sentences, syllables, lines, selected ) )
2166 {
2167 return false;
2168 }
2169 return true;
2170}
2171
2173 kdDebug(32004) << "KWTableFrameSet::finalize" << endl;
2174
2175 for (TableIter cells(this) ; cells ; ++cells)
2176 {
2177 position( cells );
2178 cells->finalize();
2179 }
2180
2181 recalcCols(0, 0);
2182 recalcRows(0, 0);
2184}
2185
2187{
2188 for (TableIter cells(this) ; cells ; ++cells)
2189 cells->layout();
2190}
2191
2192void KWTableFrameSet::invalidate()
2193{
2194 for (TableIter cells(this) ; cells ; ++cells)
2195 cells->invalidate();
2196}
2197
2199{
2200 for (TableIter cells(this) ; cells ; ++cells)
2201 cells->setVisible( v );
2202
2204}
2205
2207 /* This one is a lot simpler then the one it overrides, we simply don't have
2208 to check if the frame contains something, the simple existence of a frame
2209 is enough
2210 */
2211 TQPtrListIterator<KWFrame> frameIt( frameIterator() );
2212 for ( ; frameIt.current(); ++frameIt ) {
2213 if ( frameIt.current()->pageNumber() == num ) {
2214 return false;
2215 }
2216 }
2217 return true;
2218}
2219
2220void KWTableFrameSet::addTextFrameSets( TQPtrList<KWTextFrameSet> & lst, bool onlyReadWrite )
2221{
2222 for (TableIter cells(this) ; cells ; ++cells)
2223 if (!cells->textObject()->protectContent() || onlyReadWrite )
2224 lst.append(cells);
2225}
2226
2227KWTextFrameSet* KWTableFrameSet::nextTextObject( KWFrameSet *obj )
2228{
2229 bool found = false;
2230 KWTableFrameSet::Cell *tmp = dynamic_cast<KWTableFrameSet::Cell *>(obj);
2231
2232 // make sure we have this cell
2233 if ( tmp ) {
2234 for(TableIter i(this); i; ++i) {
2235 if(i.current() == tmp) {
2236 found = true;
2237 break;
2238 }
2239 }
2240 }
2241
2242 TableIter iter(this);
2243 if(found)
2244 iter.goToCell(tmp);
2245
2246 for(; iter; ++iter) {
2247 KWTextFrameSet *newFrm = iter->nextTextObject( obj );
2248 if(newFrm && newFrm->textObject()->needSpellCheck())
2249 return newFrm;
2250 }
2251
2252 return 0L;
2253}
2254
2256{
2257 for( TableIter cells(this) ; cells ; ++cells ) {
2258 cells->setZOrder();
2259 }
2260
2261}
2262
2263// TODO provide toPlainText() (reimplemented from KWFrameSet)
2264
2265TQByteArray KWTableFrameSet::convertTableToText() // should be const, but TableIter doesn't allow it
2266{
2267 KWOasisSaver oasisSaver( m_doc );
2268 for (TableIter cells(this); cells; ++cells)
2269 {
2270 cells->textObject()->saveOasisContent( oasisSaver.bodyWriter(), oasisSaver.savingContext() );
2271 }
2272 if ( !oasisSaver.finish() )
2273 return TQByteArray();
2274 return oasisSaver.data();
2275}
2276
2277#ifndef NDEBUG
2278void KWTableFrameSet::printDebug( KWFrame * theFrame )
2279{
2280 KWTableFrameSet::Cell *daCell = dynamic_cast<KWTableFrameSet::Cell *>( theFrame->frameSet() );
2281 Q_ASSERT( daCell );
2282 if ( daCell ) {
2283 kdDebug(32004) << " | |- row :" << daCell->firstRow() << endl;
2284 kdDebug(32004) << " | |- col :" << daCell->firstColumn() << endl;
2285 kdDebug(32004) << " | |- rows:" << daCell->rowSpan() << endl;
2286 kdDebug(32004) << " | +- cols:" << daCell->columnSpan() << endl;
2287 }
2288}
2289
2290void KWTableFrameSet::printArrayDebug() {
2291 kdDebug(32004) << " | Row/Cell arrays" << endl;
2292 Q_ASSERT( m_rows == m_rowArray.size() );
2293 for ( unsigned int row = 0; row < m_rows; ++row ) {
2294 TQString str = TQString( " | Row %1: " ).arg( row );
2295 for ( unsigned int col = 0; col < getColumns(); ++col )
2296 str += TQString("| 0x%1 ").arg( (unsigned long)(*m_rowArray[row])[col], 0, 16 );
2297 kdDebug(32004) << str<< " |" << endl;
2298 }
2299}
2300
2301void KWTableFrameSet::printDebug() {
2302 kdDebug(32004) << " | Table size (" << m_rows << "x" << getColumns() << ")" << endl;
2303 kdDebug(32004) << " | col " << 0 << ": " << m_colPositions[0] << endl;
2304 for(unsigned int i=1;i<m_colPositions.count(); ++i)
2305 kdDebug(32004) << " | | " << i << ": " << m_colPositions[i] << endl;
2306 kdDebug(32004) << " | row " << 0 << ": " << m_rowPositions[0] << endl;
2307 for(unsigned int i=1;i<m_rowPositions.count(); ++i)
2308 kdDebug(32004) << " | | " << i << ": " << m_rowPositions[i] << endl;
2309
2310 printArrayDebug();
2311 KWFrameSet::printDebug();
2312}
2313
2314#endif
2315
2316// ===
2317
2318KWTableFrameSet::Cell::Cell( KWTableFrameSet *table, unsigned int row, unsigned int col, const TQString &/*name*/ ) :
2319 KWTextFrameSet( table->m_doc,
2320 // Generate frameset name from table_name+row+col
2321 i18n("Hello dear translator :), 1 is the table name, 2 and 3 are row and column", "%1 Cell %2,%3")
2322 .arg( table->name() ).arg(row).arg(col) )
2323{
2324 m_row = row;
2325 m_col = col;
2326 m_rows = 1;
2327 m_cols = 1;
2328 m_isJoinedCell = false;
2329 setGroupManager( table );
2330 table->addCell( this );
2331}
2332
2333KWTableFrameSet::Cell::Cell( KWTableFrameSet *table, const Cell &original ) :
2334 KWTextFrameSet( table->m_doc, original.m_name+'_' )
2335{
2336 m_row = original.m_row;
2337 m_col = original.m_col;
2338 m_rows = original.m_rows;
2339 m_cols = original.m_cols;
2340 m_isJoinedCell = original.m_isJoinedCell;
2341 setGroupManager( table );
2342 table->addCell( this );
2343}
2344
2345KWTableFrameSet::Cell::~Cell()
2346{
2347}
2348
2349bool KWTableFrameSet::Cell::isAboveOrLeftOf( unsigned row, unsigned col ) const
2350{
2351 return ( m_row < row ) || ( ( m_row == row ) && ( m_col < col ) );
2352}
2353
2354bool KWTableFrameSet::Cell::containsCell( unsigned row, unsigned col ) const
2355{
2356 return ( m_row <= row &&
2357 m_col <= col &&
2358 rowAfter() > row &&
2359 columnAfter() > col );
2360}
2361
2362void KWTableFrameSet::Cell::addFrame(KWFrame *_frame, bool recalc) {
2363 if(groupmanager())
2364 groupmanager()->addFrame(_frame, recalc);
2365 KWTextFrameSet::addFrame(_frame, recalc);
2366}
2367
2369{
2370 if(groupmanager())
2371 groupmanager()->deleteFrame( frm, false, recalc );
2372}
2373
2374double KWTableFrameSet::Cell::leftBorder() {
2375 double b = frame(0)->leftBorder().width();
2376 if(b==0.0)
2377 return 0.0;
2378 if(m_col==0) // left most cell
2379 return b;
2380 return (b / 2);
2381}
2382
2383double KWTableFrameSet::Cell::rightBorder() {
2384 double b=frame(0)->rightBorder().width();
2385 if(b==0.0)
2386 return 0.0;
2387 if(m_col+m_cols==m_groupmanager->getColumns()) // right most cell
2388 return b;
2389 return (b / 2);
2390}
2391
2392double KWTableFrameSet::Cell::topBorder() {
2393 double b = frame(0)->topBorder().width();
2394 if(b==0.0)
2395 return 0.0;
2396 if(m_row==0) // top most cell
2397 return b;
2398 return (b / 2);
2399}
2400
2401double KWTableFrameSet::Cell::bottomBorder() {
2402 double b = frame(0)->bottomBorder().width();
2403 if(b==0.0)
2404 return 0.0;
2405 if(rowAfter() == m_groupmanager->m_rows) // bottom most cell
2406 return b;
2407 return (b / 2);
2408}
2409
2410void KWTableFrameSet::Cell::setLeftBorder(KoBorder newBorder) {
2411 KWFrame *f = frame(0);
2412 double diff = f->leftBorder().width() - newBorder.width();
2413 f->setLeftBorder(newBorder);
2414
2415 if((diff > 0.01 || diff < -0.01) && m_col!=0) {
2416 diff = diff / 2; // if not outer edge only use halve
2417 m_groupmanager->cell(m_row, m_col-1)->setRightBorder(newBorder);
2418 }
2419 f->setLeft(f->left() - diff);
2420}
2421
2422void KWTableFrameSet::Cell::setRightBorder(KoBorder newBorder) {
2423 KWFrame *f = frame(0);
2424 double diff = f->rightBorder().width() - newBorder.width();
2425 f->setRightBorder(newBorder);
2426
2427 if((diff > 0.01 || diff < -0.01) && m_col+m_cols!=m_groupmanager->getColumns()) {
2428 diff = diff / 2; // if not outer edge only use halve
2429 m_groupmanager->cell(m_row, m_col+1)->setLeftBorder(newBorder);
2430 }
2431 f->setRight(f->right() + diff);
2432}
2433
2434void KWTableFrameSet::Cell::setTopBorder(KoBorder newBorder) {
2435 KWFrame *f = frame(0);
2436 double diff = f->topBorder().width() - newBorder.width();
2437 f->setTopBorder(newBorder);
2438
2439 if((diff > 0.01 || diff < -0.01) && m_row!=0) {
2440 diff = diff / 2; // if not outer edge only use halve
2441 m_groupmanager->cell(m_row-1, m_col)->setBottomBorder(newBorder);
2442 }
2443 f->setTop(f->top() - diff);
2444}
2445
2446void KWTableFrameSet::Cell::setBottomBorder(KoBorder newBorder) {
2447 KWFrame *f = frame(0);
2448 double diff = f->bottomBorder().width() - newBorder.width();
2449 f->setBottomBorder(newBorder);
2450
2451 if((diff > 0.01 || diff < -0.01) && rowAfter() != m_groupmanager->m_rows) {
2452 diff = diff / 2; // if not outer edge only use halve
2453 m_groupmanager->cell(m_row+1, m_col)->setTopBorder(newBorder);
2454 }
2455 f->setBottom(f->bottom() + diff);
2456}
2457
2459{
2460 TQPtrListIterator<KWFrame> frameIt = frameIterator();
2461 for ( ; frameIt.current(); ++frameIt )
2462 {
2463 (*frameIt)->setZOrder( kWordDocument()->maxZOrder( (*frameIt)->pageNumber() ) + 1 );
2464 }
2465}
2466
2467void KWTableFrameSet::Cell::drawContents( TQPainter * painter, const TQRect & crect,
2468 const TQColorGroup & cg, bool onlyChanged, bool resetChanged,
2469 KWFrameSetEdit * edit, KWViewMode * viewMode, KWFrameViewManager *fvm )
2470{
2471 bool printing = painter->device()->devType() == TQInternal::Printer;
2472 bool drawPreviewLines = viewMode && viewMode->drawFrameBorders();
2473 TQRect cellRect = crect;
2474 if(!printing && drawPreviewLines) {
2475 // Make sure the clipping is changed so the preview lines (frame borders) are not overwritten.
2476 TQRect zoomedRect( m_doc->zoomRect(*frame(0)) );
2477 TQRect innerFrameRect( viewMode->normalToView( zoomedRect ) );
2478 innerFrameRect.addCoords(1, 1, -1, -1); // move and shrink
2479 cellRect = innerFrameRect.intersect(crect);
2480 }
2481 KWTextFrameSet::drawContents(painter, cellRect, cg, onlyChanged, resetChanged, edit, viewMode, fvm);
2482}
2483
2484KWTableFrameSetEdit::~KWTableFrameSetEdit()
2485{
2486 if ( m_currentCell )
2487 m_currentCell->terminate();
2488 delete m_currentCell;
2489}
2490
2491void KWTableFrameSetEdit::mousePressEvent( TQMouseEvent * e, const TQPoint & nPoint, const KoPoint & dPoint )
2492{
2493 setCurrentCell( dPoint );
2494 if ( m_currentCell )
2495 m_currentCell->mousePressEvent( e, nPoint, dPoint );
2496}
2497
2498void KWTableFrameSetEdit::setCurrentCell( const KoPoint & dPoint )
2499{
2500 KWFrameSet *fs = tableFrameSet()->cellByPos( dPoint.x(), dPoint.y() );
2501 KWTextFrameSet *textframeSet = dynamic_cast<KWTextFrameSet *>(fs);
2502
2503 if ( textframeSet&& textframeSet->protectContent() && !tableFrameSet()->kWordDocument()->cursorInProtectedArea())
2504 return;
2505
2506 if ( fs && ( !m_currentCell || fs != m_currentCell->frameSet() ) )
2507 setCurrentCell( fs );
2508}
2509
2510void KWTableFrameSetEdit::setCurrentCell( KWFrameSet * fs, bool eraseSelection )
2511{
2512 bool oldProtectContent = false;
2513 KWTextFrameSet *textframeSet=0L;
2514 if ( m_currentCell )
2515 textframeSet = dynamic_cast<KWTextFrameSet *>(m_currentCell->frameSet());
2516 if ( textframeSet )
2517 oldProtectContent = textframeSet->protectContent();
2518
2519 if ( m_currentCell )
2520 {
2521 m_currentCell->terminate(eraseSelection);
2522 delete m_currentCell;
2523 }
2524 m_currentCell = fs->createFrameSetEdit( m_canvas );
2525 textframeSet = dynamic_cast<KWTextFrameSet *>(m_currentCell->frameSet());
2526 if ( textframeSet )
2527 {
2528 if ( oldProtectContent != textframeSet->protectContent())
2529 {
2530 m_canvas->kWordDocument()->updateTextFrameSetEdit();
2531 }
2532 }
2533
2534
2535 m_currentFrame = fs->frame( 0 );
2536 KWTextFrameSetEdit *textframeSetEdit = dynamic_cast<KWTextFrameSetEdit *>(m_currentCell);
2537 if ( textframeSetEdit )
2538 {
2539 textframeSetEdit->ensureCursorVisible();
2540 //refresh koruler
2541 m_canvas->gui()->getView()->slotUpdateRuler();
2542 }
2543}
2544
2546{
2547 return m_currentCell;
2548}
2549
2550
2551void KWTableFrameSetEdit::keyPressEvent( TQKeyEvent * e )
2552{
2553 // This method handles the up/left/down/right navigation keys in tables
2554 if ( !m_currentCell )
2555 return;
2556 KWTableFrameSet::Cell *cell = static_cast<KWTableFrameSet::Cell *>(m_currentCell->frameSet());
2557 KWTextFrameSet *textframeSet = dynamic_cast<KWTextFrameSet *>(m_currentCell->frameSet());
2558 bool moveToOtherCell = true;
2559 if(textframeSet)
2560 {
2561 // don't move to an adjacent cell when we are selecting text
2562 KoTextDocument * textdoc = textframeSet->textDocument();
2563 if(textdoc->hasSelection( KoTextDocument::Standard ))
2564 moveToOtherCell=false;
2565 }
2566 KWTableFrameSet::Cell *fs = 0L;
2567
2568 bool tab=false; // No tab key pressed
2569 if(moveToOtherCell)
2570 {
2571 switch( e->key() ) {
2572 case TQt::Key_Up:
2573 {
2574 if(!(static_cast<KWTextFrameSetEdit *>(m_currentCell))->cursor()->parag()->prev())
2575 {
2576 KWTableFrameSet* tableFrame=tableFrameSet();
2577 int row = cell->firstRow() - 1;
2578 int col = cell->firstColumn();
2579 if (row < 0) { // Wrap at top of table
2580 col--; // Goes to column on the left
2581 row = tableFrame->getRows() - 1;
2582 }
2583 if (col < 0) { // It was the first column
2584 // Maybe exit the table instead?
2585 col = tableFrame->getColumns() - 1;
2586 row = tableFrame->getRows() - 1;
2587 }
2588 fs=tableFrame->cell(row,col);
2589 // Not needed. cell gives us the right one already
2590 //if (fs && fs->firstRow() != static_cast<unsigned int>(row)) { // Merged cell
2591 // fs=tableFrame->cell( row - fs->rowSpan() + 1, col );
2592 //}
2593 }
2594 }
2595 break;
2596 case TQt::Key_Down:
2597 {
2598 if(!(static_cast<KWTextFrameSetEdit *>(m_currentCell))->cursor()->parag()->next())
2599 {
2600 KWTableFrameSet* tableFrame=tableFrameSet();
2601 unsigned int row = cell->rowAfter();
2602 unsigned int col = cell->firstColumn();
2603 if(row >= tableFrame->getRows()) { // Wrap at bottom of table
2604 row=0;
2605 col++; // Go to next column
2606 }
2607 if(col >= tableFrame->getColumns()) { // It was the last one
2608 // Maybe exit the table instead?
2609 col=0;
2610 row=0;
2611 }
2612 fs=tableFrame->cell(row,col);
2613 Q_ASSERT( fs );
2614 Q_ASSERT( fs->firstRow() == row ); // We can't end up in the middle of a merged cell here.
2615 }
2616 }
2617 break;
2618 case TQt::Key_Backtab:
2619 tab=true;
2620 if (e->state() & TQt::ControlButton)
2621 break; // Break if tab was pressed with Control (in *any* key combination)
2622 // Do not break
2623 case TQt::Key_Left:
2624 {
2625 KoTextCursor *cur = (static_cast<KWTextFrameSetEdit *>(m_currentCell))->cursor();
2626 if ( tab || (!cur->parag()->prev()&&cur->index()==0) )
2627 {
2628 KWTableFrameSet* tableFrame=tableFrameSet();
2629 int row=cell->firstRow();
2630 int col=cell->firstColumn() - 1;
2631 if(col < 0) { // Wrap at first column
2632 col = (int)tableFrame->getColumns()-1;
2633 row--; // Go up
2634 }
2635 if(row < 0) { // It was the first row
2636 // Maybe exit the table instead?
2637 col = (int)tableFrame->getColumns()-1;
2638 row = (int)tableFrame->getRows()-1;
2639 }
2640 fs=tableFrame->cell(row,col);
2641 // Not needed. cell gives us the right one already
2642 //if(fs && (int)fs->m_col != col) { // Merged cell
2643 // fs=tableFrame->cell( row, col - fs->columnSpan() + 1 );
2644 //}
2645 }
2646 }
2647 break;
2648 case TQt::Key_Tab:
2649 tab=true;
2650 if (e->state() & TQt::ControlButton)
2651 break; // Break if tab was pressed with Control (in *any* key combination)
2652 // Do not break
2653 case TQt::Key_Right:
2654 {
2655 KoTextCursor *cur = (static_cast<KWTextFrameSetEdit *>(m_currentCell))->cursor();
2656 if( tab || (!cur->parag()->next()&&cur->index()==cur->parag()->string()->length()-1) )
2657 {
2658 KWTableFrameSet* tableFrame=tableFrameSet();
2659 unsigned int row = cell->firstRow();
2660 unsigned int col = cell->columnAfter();
2661 if(col >= tableFrame->getColumns()) { // Wrap after last column
2662 col = 0;
2663 row++; // Go down one row
2664 }
2665 if(row >= tableFrame->getRows()) { // It was the last row
2666 // Maybe exit the table instead?
2667 col = 0;
2668 row = 0;
2669 }
2670 fs=tableFrame->cell(row,col);
2671 Q_ASSERT( fs );
2672 Q_ASSERT( fs->firstRow() == row ); // We can't end up in the middle of a merged cell here.
2673 }
2674 }
2675 break;
2676 }
2677 }
2678 if ( fs )
2679 {
2680 //don't switch to a protected cell protected when cursor in protected areas was disabled.
2681 if ( fs->textObject()->protectContent() && !tableFrameSet()->kWordDocument()->cursorInProtectedArea())
2682 return;
2683 setCurrentCell( fs );
2684 }
2685 else if ( textframeSet )
2686 {
2687 if ( !textframeSet->textObject()->protectContent() )
2688 {
2689 if (tab && (e->state() & TQt::ControlButton) )
2690 {
2691 TQKeyEvent event(TQEvent::KeyPress, TQt::Key_Tab, 9, 0, TQChar(9));
2692 m_currentCell->keyPressEvent( &event );
2693 }
2694 else
2695 m_currentCell->keyPressEvent( e );
2696 }
2697 else if(e->text().length() > 0)
2698 KMessageBox::information(0L, i18n("Read-only content cannot be changed. No modifications will be accepted."));
2699 }
2700}
2701
2702void KWTableFrameSetEdit::keyReleaseEvent( TQKeyEvent * e )
2703{
2704 if ( m_currentCell )
2705 m_currentCell->keyReleaseEvent( e );
2706}
2707
2708void KWTableFrameSetEdit::imStartEvent( TQIMEvent* e )
2709{
2710 if ( m_currentCell )
2711 m_currentCell->imStartEvent( e );
2712}
2713
2714void KWTableFrameSetEdit::imComposeEvent( TQIMEvent* e )
2715{
2716 if ( m_currentCell )
2717 m_currentCell->imComposeEvent( e );
2718}
2719
2720void KWTableFrameSetEdit::imEndEvent( TQIMEvent* e )
2721{
2722 if ( m_currentCell )
2723 m_currentCell->imEndEvent( e );
2724}
2725
2726void KWTableFrameSetEdit::dragMoveEvent( TQDragMoveEvent * e, const TQPoint &n, const KoPoint &d )
2727{
2728 kdDebug(32004)<<"m_currentCell :"<<m_currentCell<<endl;
2729 if ( m_currentCell )
2730 {
2731 KWFrameSet *fs = tableFrameSet()->cellByPos( d.x(), d.y() );
2732 kdDebug(32004)<<"fs :"<<fs <<endl;
2733 if(fs && fs != m_currentCell->frameSet())
2734 setCurrentCell(fs, false);
2735 if(m_currentCell)
2736 m_currentCell->dragMoveEvent( e, n, d );
2737 }
2738 else
2739 {
2740 setCurrentCell( d );
2741 kdDebug(32004)<<"after m_currentCell :"<<m_currentCell<<endl;
2742 if(m_currentCell)
2743 m_currentCell->dragMoveEvent( e, n, d );
2744 }
2745}
2746
2747void KWTableFrameSet::Row::addCell( Cell *cell )
2748{
2749 if ( m_cellArray.size() < cell->columnAfter())
2750 m_cellArray.resize( cell->columnAfter() );
2751 for ( uint col = cell->firstColumn() ; col < cell->columnAfter(); ++col )
2752 m_cellArray.insert( col, cell );
2753}
2754
2755void KWTableFrameSet::Row::removeCell( Cell* cell )
2756{
2757 for ( uint col = cell->firstColumn() ; col < cell->columnAfter(); ++col )
2758 m_cellArray.remove( col );
2759}
2760
2761template<>
2764{
2765 if(!m_cell) return 0;
2766
2767 Cell *ret = m_cell;
2768
2769 do{
2770 // check for end of row first
2771 if(m_table->cell(m_row,m_col)->lastColumn() >= m_limit[RIGHT] ) {
2772 // now check for end of column
2773 if (m_row >= m_limit[LOW]){
2774 // at end of traversal
2775 m_cell = 0;
2776 break;
2777 }
2778 else {
2779 // goto first grid position in next row
2780 m_row += 1;
2781 m_col = m_limit[LEFT];
2782 }
2783 }
2784 else {
2785 // goto next cell in row
2786 m_col = m_table->cell(m_row, m_col)->columnAfter();
2787 }
2788
2789 m_cell = m_table->cell(m_row,m_col);
2790 } while( m_cell && !m_cell->isFirstGridPosnFast(m_row,m_col) );
2791
2792 return ret;
2793}
2794
2795template<>
2798{
2799 if(!m_cell) return 0;
2800
2801 Cell *ret = m_cell;
2802 // check for end of row
2803 if(m_col == m_limit[RIGHT]) {
2804 if(m_row == m_limit[LOW]) { // end of traversal
2805 m_row = 0;
2806 m_col = 0;
2807 m_cell = 0;
2808 }
2809 else { // go to next row
2810 m_row += 1;
2811 m_col = m_limit[LEFT];
2812 m_cell = m_table->cell(m_row, m_col);
2813 }
2814 }
2815 else { // move to next cell in row
2816 m_col += 1;
2817 m_cell = m_table->cell(m_row, m_col);
2818 }
2819
2820 return ret;
2821}
2822
2823KWTableFrameSet::MarkedIterator::MarkedIterator(KWTableFrameSet *table) :
2824 GridIter(table)
2825{
2826 // clear all the cell marks
2827 for(GridIter cell(table); cell; ++cell)
2828 cell->clearMark();
2829
2830 if ( current() ) {
2831// kdDebug() << "MarkedIterator: visit: "
2832// << TQString("| 0x%1 ").arg((unsigned long)current(), 0, 16) << endl;
2833 current()->setMark();
2834 }
2835}
2836
2838KWTableFrameSet::MarkedIterator::operator++()
2839{
2840 Cell *ret = GridIter::operator++();
2841
2842 while ( current() && current()->marked() ) {
2843 GridIter::operator++();
2844 }
2845 if ( current() ) {
2846// kdDebug() << "MarkedIterator: visit: "
2847// << TQString("| 0x%1 ").arg((unsigned long)current(), 0, 16) << endl;
2848 current()->setMark();
2849 }
2850 return ret;
2851}
2852
2853template<>
2855 m_table(table)
2856{
2857 Q_ASSERT(m_table);
2858 set_limits(0, (int)m_table->getColumns() - 1, 0, (int)m_table->getRows() - 1);
2859
2860 Cell *c = 0;
2861 for(uint i = m_limit[HIGH]; i <= m_limit[LOW]; ++i)
2862 for(uint j = m_limit[LEFT]; j <= m_limit[RIGHT]; ++j) {
2863
2864 c = m_table->cell(i,j);
2865 if(c) c->clearMark();
2866 }
2867 toFirstCell();
2868}
2869
2870template<>
2873{
2874
2875 Cell *ret = m_cell;
2876 if(!ret) return 0;
2877
2878 ret->setMark();
2879 m_cell = 0;
2880 uint i = m_row; uint j = m_col;
2881
2882 for(; i <= m_limit[LOW]; ++i) {
2883
2884 for(j = 0; j <= m_limit[RIGHT]; ++j) {
2885 m_cell = m_table->cell(i,j);
2886 if( m_cell && !m_cell->marked() ){
2887 m_row = i; m_col = j;
2888 goto out;
2889 }
2890 else if(i == m_limit[LOW] && j == m_limit[RIGHT]){
2891 m_cell = 0;
2892 goto out;
2893 }
2894 }
2895 }
2896
2897 out:
2898 return ret;
2899}
2900
2901template<>
2904{
2905 m_cell = 0;
2906 for(uint i = m_limit[HIGH]; i <= m_limit[LOW]; ++i)
2907 for(uint j = m_limit[LEFT]; j <= m_limit[RIGHT]; ++j) {
2908 m_cell = m_table->cell(i,j);
2909 if(m_cell) {
2910 m_row = i; m_col = j;
2911 goto out;
2912 }
2913 }
2914
2915 out:
2916 return m_cell;
2917}
2918
2919RemovedRow::RemovedRow() :
2920 m_row(0), m_index(0), m_rowHeight(0.0)
2921{
2922
2923}
2924
2925RemovedRow::~RemovedRow()
2926{
2927 // free cells as well ???
2928 delete m_row;
2929}
2930
2931KWTableFrameSet::Row *RemovedRow::takeRow()
2932{
2933 Q_ASSERT(m_row);
2934 KWTableFrameSet::Row *ret = m_row;
2935 m_row = 0;
2936 return ret;
2937}
2938
2939RemovedColumn::RemovedColumn()
2940 : m_column(), m_removed(), m_index(0), m_width(0), m_initialized(false){ }
2941
2942
2943#include "KWTableFrameSet.moc"
An anchor is a special character, or 'custom item'.
Definition KWAnchor.h:35
Class: KWCanvas This class is responsible for the rendering of the frames to the screen as well as th...
Definition KWCanvas.h:61
Command created when creating a table.
Definition KWCommand.h:481
Command created when deleting a table.
Definition KWCommand.h:465
void updateAfterMove(int oldPageNum)
Update the z-ordering around the frame we host the framelist for.
This object is created to edit a particular frameset in a particular view The view's canvas creates i...
virtual void drawContents(TQPainter *, const TQRect &, const TQColorGroup &, bool onlyChanged, bool resetChanged, KWViewMode *viewMode, KWFrameViewManager *frameViewManager)
Paint this frameset in "has focus" mode (e.g.
Class: KWFrameSet Base type, a frameset holds content as well as frames to show that content.
Definition KWFrameSet.h:62
void repaintChanged(KWFrameSet *frameset)
Emitted when something has changed in this frameset, so that all views repaint it.
KWAnchor * findAnchor(int frameNum)
Return the anchor object for this frame number.
virtual void setVisible(bool v)
set the visibility of the frameset.
virtual void deleteFrame(unsigned int num, bool remove=true, bool recalc=true)
Delete a frame from the set of frames this frameSet has.
const TQPtrList< KWFrame > & frameIterator() const
Iterator over the child frames.
Definition KWFrameSet.h:159
virtual void finalize()
Called once the frameset has been completely loaded or constructed.
virtual KWFrameSetEdit * createFrameSetEdit(KWCanvas *)
Create a framesetedit object to edit this frameset in canvas.
Definition KWFrameSet.h:169
virtual void load(TQDomElement &framesetElem, bool loadFrames=true)
load from XML - when loading
bool isFloating() const
Return true if this frameset is floating (inline), false if it's fixed.
Definition KWFrameSet.h:372
virtual void updateFrames(int flags=0xff)
Called when our frames change, or when another frameset's frames change.
void saveCommon(TQDomElement &parentElem, bool saveFrames)
save the common attributes for the frameset
virtual void setZOrder()
set z-order for all frames
KWTableFrameSet * groupmanager() const
returns the groupManager this frameset belongs to.
Definition KWFrameSet.h:408
KWFrame * frame(unsigned int _num) const
get a frame by number
TQString name() const
get/set frameset name. For tables in particular, this must be unique
Definition KWFrameSet.h:428
KWFrame * frameAtPos(double _x, double _y) const
retrieve frame from x and y coords (unzoomed coords)
void setGroupManager(KWTableFrameSet *gm)
make this frameset part of a groupmanager
Definition KWFrameSet.h:406
Class that knows about all the (visible) frames in the document and will act as a manager between the...
This class represents a single frame.
Definition KWFrame.h:68
KWFrameSet * frameSet() const
Data stucture methods.
Definition KWFrame.h:143
void setPaddingLeft(double b)
set left padding (distance between frame contents and frame border)
Definition KWFrame.h:227
void setMinimumFrameHeight(double h)
The property minimum frame height is used to make the automatic frame shrinking code stop.
Definition KWFrame.h:279
void setPaddingRight(double b)
set right padding
Definition KWFrame.h:229
void setPaddingBottom(double b)
set bottom padding
Definition KWFrame.h:233
void setPaddingTop(double b)
set top padding
Definition KWFrame.h:231
int pageNumber() const
The page on which this frame is.
Definition KWFrame.cpp:116
const KoBorder & leftBorder() const
All borders can be custom drawn with their own colors etc.
Definition KWFrame.h:170
KWFrame * getCopy()
returns a copy of self
Definition KWFrame.cpp:135
Command created when joining cells.
Definition KWCommand.h:589
This is used to save a bunch of paragraphs into a oasis store in memory, as some features do (e....
KWPage * page(int pageNumber) const
return the KWPage of a specific page number. Returns 0 if page does not exist.
This class represents a printed page of the document.
Definition KWPage.h:30
double leftMargin() const
return the width of the margin at left (in pt);
Definition KWPage.cpp:97
double width() const
return the width of this page (in pt)
Definition KWPage.cpp:38
double rightMargin() const
return the width of the margin at left (in pt);
Definition KWPage.cpp:108
Command created when splitting a cell.
Definition KWCommand.h:569
The object created to edit this table.
virtual KWFrameSetEdit * currentTextEdit()
Return the current most-low-level text edit object.
void setCurrentCell(KWFrameSet *fs, bool eraseSelection=true)
Set the cell which is currently being edited.
virtual void frameDeleted(KWFrame *frm, bool recalc)
Called by deleteFrame when it really deletes a frame (remove=true), to remove it from the table too.
Cell(KWTableFrameSet *table, unsigned int row, unsigned int col, const TQString &name=TQString())
constructor
void drawContents(TQPainter *painter, const TQRect &crect, const TQColorGroup &cg, bool onlyChanged, bool resetChanged, KWFrameSetEdit *edit, KWViewMode *viewMode, KWFrameViewManager *frameViewManager)
Overloaded to not clear any preview borders.
void setZOrder()
set zorder for all frames in this cell
This iterator does not look at the Cell instance variables during traversal, (except m_marker),...
Represents a row, for direct access to cells with m_rowArray[row][column].
TQPtrVector< Cell > m_cellArray
Array of cells in the row.
All the TableIterator templates are the same, except for the pre-increment operator (operator++).
TableIterator(KWTableFrameSet *table)
This class implements tables by acting as the manager for the frame(set)s which make up the table cel...
void resizeWidth(double width)
change the width of the table, keeping the proportions of the cells (if one is wider than the others,...
virtual void finalize()
Called once the frameset has been completely loaded or constructed.
Cell * loadCell(TQDomElement &frameElem, bool loadFrames=true, bool useNames=true)
load one cell
virtual void layout()
relayout text in frames, so that it flows correctly around other frames
void insertNewColumn(uint _idx, double width=KWTableFrameSet::m_sDefaultColWidth)
insert a column of new cells use the getRows() call to decide how many cells are created
void moveBy(double dx, double dy)
move the whole of the table, this is mainly for anchored frames.
virtual KCommand * anchoredObjectCreateCommand(int frameNum)
Store command for creating an anchored object.
void setZOrder()
Sets zOrder for all cells in this table.
virtual KCommand * anchoredObjectDeleteCommand(int frameNum)
Store command for deleting an anchored object.
void resizeColumn(unsigned int col, double x)
move a column edge (i.e.
virtual TQDomElement save(TQDomElement &parentElem, bool saveFrames=true)
override save so we save in table style.
virtual int paragraphs()
Contribute to the document statistics.
virtual void moveFloatingFrame(int frameNum, const KoPoint &position)
Move the frame frameNum to the given position - this is called when the frame is anchored and the anc...
void removeCell(Cell *cell)
Remove a cell from this table (either to delete it, or to move it)
void reInsertRow(RemovedRow &row)
replace a row that was removed with deleteRow()
void ungroup()
release the constrains of the table and allow all frames to be edited apart from each other.
virtual void updateFrames(int flags=0xff)
Called when our frames change, or when another frameset's frames change.
virtual void drawContents(TQPainter *painter, const TQRect &crect, const TQColorGroup &cg, bool onlyChanged, bool resetChanged, KWFrameSetEdit *edit, KWViewMode *viewMode, KWFrameViewManager *frameViewManager)
Paint this frameset.
void validate()
do a number of complex tests to test the validity of the table.
virtual TQDomElement toXML(TQDomElement &parentElem, bool saveFrames=true)
from and to XML - used when copying and pasting a table
virtual void createEmptyRegion(const TQRect &crect, TQRegion &emptyRegion, KWViewMode *viewMode)
KoRect boundingRect()
Calculate the absolute size of the complete table.
void setBoundingRect(KoRect rect, CellSize widthMode, CellSize heightMode)
Layout all cells to fit inside the rect, cells will however use a minimum size, so the table might en...
void deleteColumn(uint _idx, RemovedColumn &rc)
remove all the cells in a certain column
void insertNewRow(uint _idx, bool _recalc=true, bool _removeable=false)
insert a row of new cells, use the getCols() call to decide how many cells are created
KCommand * splitCell(unsigned int intoRows, unsigned int intoColumns, unsigned int column, unsigned int row, TQPtrList< KWFrameSet > listFrameSet=TQPtrList< KWFrameSet >(), TQPtrList< KWFrame >listFrame=TQPtrList< KWFrame >())
split one cell into a number of cells and return a command for undo purposes.
double topWithoutBorder()
Calculate the top postion of the cell(s) in the leftmost column.
virtual KoSize floatingFrameSize(int frameNum=0)
Get the size of the "floating frame" identified by frameNum.
int columnEdgeAt(double x) const
return the number of the column edge closest to x (between 0 and getCols()+1)
virtual void setVisible(bool v)
set the visibility of the frameset.
void reInsertColumn(RemovedColumn &col)
replace a column that was removed with deleteColumn()
void recalcCols(uint column, uint row)
resize and position all cells
unsigned int getColumns() const
returns the number of columns
void resizeRow(unsigned int row, double y)
move a row edge (i.e.
virtual KWAnchor * createAnchor(KoTextDocument *txt, int frameNum)
Create an anchor for the floating frame identified by frameNum.
int rowEdgeAt(double y) const
return the number of the row edge closest to x (between 0 and getRows()+1)
virtual void fromXML(TQDomElement &framesetElem, bool loadFrames=true, bool useNames=true)
load from XML - when pasting from clipboard
void addCell(Cell *cell)
Add a cell to this table, the cell should already have info like row, col and should already have a f...
virtual bool canRemovePage(int num)
Return true if page num can be removed, as far as this frameset is concerned.
double leftWithoutBorder()
Calculate the top postion of the cell(s) in the top row.
virtual void saveOasis(KoXmlWriter &, KoSavingContext &, bool saveFrames) const
Save to OASIS format.
void deleteRow(uint _idx, RemovedRow &rr, bool _recalc=true)
Remove all the cells in a certain row.
KWTableFrameSet(KWDocument *_doc, const TQString &name)
constructor
void viewFormatting(TQPainter &painter, int zoom)
display formatting information
KCommand * joinCells(unsigned int firstColumn, unsigned int firstRow, unsigned int endColumn, unsigned int endRow)
merge cells to one cell.
virtual KWFrameSetEdit * createFrameSetEdit(KWCanvas *canvas)
Create a framesetedit object to edit this frameset in canvas.
virtual ~KWTableFrameSet()
destructor
unsigned int getRows() const
returns the number of rows
Object that is created to edit a Text frame set (KWTextFrameSet).
Class: KWTextFrameSet Contains text (KoTextObject) and frames to display that text.
KoTextObject * textObject() const
Return the contained text object.
virtual void load(TQDomElement &attributes, bool loadFrames=true)
load from XML - when loading
virtual void deleteFrame(unsigned int num, bool remove=true, bool recalc=true)
Delete a frame from the set of frames this frameSet has.
void saveOasisContent(KoXmlWriter &writer, KoSavingContext &context) const
Save the contents of a frame (i.e. the text)
virtual KWTextFrameSet * nextTextObject(KWFrameSet *)
Iteration over text objects - used by KWBgSpellCheck.
virtual void drawContents(TQPainter *painter, const TQRect &crect, const TQColorGroup &cg, bool onlyChanged, bool resetChanged, KWFrameSetEdit *edit, KWViewMode *viewMode, KWFrameViewManager *frameViewManager)
Paint this frameset.
Abstract base class for KWCanvas's view modes.
Definition KWViewMode.h:48
virtual TQPoint normalToView(const TQPoint &nPoint)=0
Normal coord -> view coord.
bool drawFrameBorders() const
Should we see frame borders? This setting doesn't always come from KWView...
Definition KWViewMode.h:105
RemovedRow and RemovedColumn implement the Memento design pattern.