Common subdirectories: kword/CVS and kword-m_cells/CVS Common subdirectories: kword/data and kword-m_cells/data Common subdirectories: kword/demos and kword-m_cells/demos Common subdirectories: kword/.deps and kword-m_cells/.deps diff -uNp --exclude-from=/home/carl/kde-devel/.diffignore kword/docstruct.cc kword-m_cells/docstruct.cc --- kword/docstruct.cc 2003-05-13 07:32:46.000000000 +1000 +++ kword-m_cells/docstruct.cc 2003-06-08 12:41:45.000000000 +1000 @@ -174,7 +174,7 @@ void KWDocStructTableItem::selectFrameSe void KWDocStructTableItem::editFrameSet() { //active the first cell - gui->canvasWidget()->editTextFrameSet( table->getCell(0), 0L, 0 ); + gui->canvasWidget()->editTextFrameSet( table->getCell(0,0), 0L, 0 ); } void KWDocStructTableItem::deleteFrameSet() Common subdirectories: kword/dtd and kword-m_cells/dtd Common subdirectories: kword/expression and kword-m_cells/expression Common subdirectories: kword/horizontalline and kword-m_cells/horizontalline diff -uNp --exclude-from=/home/carl/kde-devel/.diffignore kword/kwcanvas.cc kword-m_cells/kwcanvas.cc --- kword/kwcanvas.cc 2003-05-25 00:32:36.000000000 +1000 +++ kword-m_cells/kwcanvas.cc 2003-06-08 12:41:45.000000000 +1000 @@ -547,7 +547,7 @@ void KWCanvas::contentsMousePressEvent( KWTableFrameSet::Cell *cell = table->getCellByPos( table->leftWithoutBorder(), m_doc->unzoomItY(normalPoint.y()) ); if (cell) { - table->selectRow( cell->getRow() ); + table->selectRow( cell->firstRow() ); curTable = table; emit frameSelectedChanged(); } @@ -558,7 +558,7 @@ void KWCanvas::contentsMousePressEvent( KWTableFrameSet::Cell *cell = table->getCellByPos( m_doc->unzoomItX(normalPoint.x()), table->topWithoutBorder() ); if (cell) { - table->selectCol( cell->getColumn() ); + table->selectCol( cell->firstCol() ); curTable = table; emit frameSelectedChanged(); } @@ -1068,8 +1068,8 @@ void KWCanvas::mmEditFrameMove( const QP //kdDebug() << "KWCanvas::mmEditFrameMove TABLESMOVED" << endl; for ( unsigned int i = 0; i < tablesMoved.count(); i++ ) { KWTableFrameSet *table = tablesMoved.at( i ); - for ( unsigned k = 0; k < table->getNumCells(); k++ ) { - KWFrame * frame = table->getCell( k )->frame( 0 ); + for ( KWTableFrameSet::TableIter k(table) ; k ; ++k ) { + KWFrame * frame = k->frame( 0 ); QRect oldRect( m_viewMode->normalToView( frame->outerRect() ) ); frame->moveTopLeft( frame->topLeft() + _move ); // Calculate new rectangle for this frame diff -uNp --exclude-from=/home/carl/kde-devel/.diffignore kword/kwcommand.cc kword-m_cells/kwcommand.cc --- kword/kwcommand.cc 2003-06-08 01:40:04.000000000 +1000 +++ kword-m_cells/kwcommand.cc 2003-06-08 12:41:45.000000000 +1000 @@ -1108,17 +1108,17 @@ KWUngroupTableCommand::KWUngroupTableCom m_pTable(_table) { m_ListFrame.clear(); - for ( unsigned int i = 0; i < m_pTable->getNumCells(); i++ ) { - m_ListFrame.append(m_pTable->getCell( i )); + for ( KWTableFrameSet::TableIter i(m_pTable); i ; ++i ) { + m_ListFrame.append( i.current() ); } } void KWUngroupTableCommand::execute() { KWDocument * doc = m_pTable->kWordDocument(); - for ( unsigned int i = 0; i < m_pTable->getNumCells(); i++ ) { - m_pTable->getCell( i )->setGroupManager( 0L ); - doc->addFrameSet(m_pTable->getCell( i )); + for ( KWTableFrameSet::TableIter i(m_pTable) ; i ; ++i ) { + i->setGroupManager( 0L ); + doc->addFrameSet( i.current() ); } m_pTable->ungroup(); doc->removeFrameSet(m_pTable); @@ -1202,12 +1202,17 @@ void KWDeleteTableCommand::unexecute() KWInsertColumnCommand::KWInsertColumnCommand( const QString &name, KWTableFrameSet * _table, int _col, double _maxRight ): KNamedCommand(name), m_pTable(_table), + m_rc(new RemovedColumn()), m_colPos(_col), m_maxRight(_maxRight), m_oldWidth(0) { Q_ASSERT(m_pTable); - m_ListFrameSet.clear(); +} + +KWInsertColumnCommand::~KWInsertColumnCommand() +{ + delete m_rc; } void KWInsertColumnCommand::execute() @@ -1224,11 +1229,11 @@ void KWInsertColumnCommand::execute() double newColSize = newTableWidth / (m_pTable->getCols()+1); double resizeTableWidth = m_maxRight - m_pTable->boundingRect().left(); m_pTable->resizeWidth(resizeTableWidth - newColSize); - m_pTable->insertCol(m_colPos, m_ListFrameSet, QPtrList(), newColSize); + m_pTable->insertNewCol(m_colPos, newColSize); } else { // simply insert the column without asking for a specific size : - m_pTable->insertCol(m_colPos, m_ListFrameSet); + m_pTable->insertNewCol(m_colPos); } Q_ASSERT(m_pTable->boundingRect().right() <= m_maxRight); doc->updateAllFrames(); @@ -1241,17 +1246,9 @@ void KWInsertColumnCommand::unexecute() { kdDebug() << "KWInsertColumnCommand::unexecute" << endl; KWDocument * doc = m_pTable->kWordDocument(); - if(m_ListFrameSet.isEmpty()) - { - for ( unsigned int i = 0; i < m_pTable->getNumCells(); i++ ) { - KWTableFrameSet::Cell *cell=static_cast(m_pTable->getCell( i )); - if(cell->firstCol() == m_colPos) - m_ListFrameSet.append(cell); - } - } doc->terminateEditing(m_pTable); doc->frameSelectedChanged(); - m_pTable->deleteCol( m_colPos); + m_pTable->deleteCol(m_colPos, *m_rc); // now undo the resize of the table if necessary: if (m_oldWidth) { // yes, the table was resized, let's undo that : @@ -1268,17 +1265,28 @@ void KWInsertColumnCommand::unexecute() KWInsertRowCommand::KWInsertRowCommand( const QString &name, KWTableFrameSet * _table, int _row ): KNamedCommand(name), m_pTable(_table), - m_rowPos(_row) + m_rr(new RemovedRow()), + m_rowPos(_row), + m_inserted(false) { Q_ASSERT(m_pTable); - m_ListFrameSet.clear(); +} + +KWInsertRowCommand::~KWInsertRowCommand() +{ + delete m_rr; } void KWInsertRowCommand::execute() { kdDebug() << "KWInsertRowCommand::execute" << endl; KWDocument * doc = m_pTable->kWordDocument(); - m_pTable->insertRow( m_rowPos,m_ListFrameSet); + if(m_inserted) + m_pTable->reInsertRow(*m_rr); + else { + m_inserted = true; + m_pTable->insertNewRow(m_rowPos); //only happens the first time + } doc->updateAllFrames(); doc->layout(); doc->updateResizeHandles( ); @@ -1289,16 +1297,10 @@ void KWInsertRowCommand::unexecute() { kdDebug() << "KWInsertRowCommand::unexecute" << endl; KWDocument * doc = m_pTable->kWordDocument(); - if(m_ListFrameSet.isEmpty()) - { - for ( unsigned int i = 0; i < m_pTable->getNumCells(); i++ ) { - KWTableFrameSet::Cell *cell=static_cast(m_pTable->getCell( i )); - if(cell->firstRow() == m_rowPos) - m_ListFrameSet.append(cell); - } - } + doc->terminateEditing(m_pTable); - m_pTable->deleteRow( m_rowPos); + m_pTable->deleteRow( m_rowPos, *m_rr); + doc->frameSelectedChanged(); doc->updateAllFrames(); doc->layout(); @@ -1307,35 +1309,28 @@ void KWInsertRowCommand::unexecute() } - - KWRemoveRowCommand::KWRemoveRowCommand( const QString &name, KWTableFrameSet * _table, int _row ): KNamedCommand(name), m_pTable(_table), + m_rr(new RemovedRow()), m_rowPos(_row) { Q_ASSERT(m_pTable); } +KWRemoveRowCommand::~KWRemoveRowCommand() +{ + delete m_rr; +} + void KWRemoveRowCommand::execute() { kdDebug() << "KWRemoveRowCommand::execute" << endl; KWDocument * doc = m_pTable->kWordDocument(); doc->terminateEditing(m_pTable); - m_ListFrameSet.clear(); - m_copyFrame.clear(); - for ( unsigned int i = 0; i < m_pTable->getNumCells(); i++ ) - { - KWTableFrameSet::Cell *cell=static_cast(m_pTable->getCell( i )); - if(cell->firstRow() == m_rowPos) - { - m_ListFrameSet.append(cell); - m_copyFrame.append(cell->frame(0)->getCopy()); - } - } + m_pTable->deleteRow( m_rowPos, *m_rr); - m_pTable->deleteRow( m_rowPos); doc->frameSelectedChanged(); doc->updateAllFrames(); doc->layout(); @@ -1347,41 +1342,34 @@ void KWRemoveRowCommand::unexecute() { kdDebug() << "KWRemoveRowCommand::unexecute" << endl; KWDocument * doc = m_pTable->kWordDocument(); - m_pTable->insertRow( m_rowPos,m_ListFrameSet,m_copyFrame); + m_pTable->reInsertRow(*m_rr); doc->updateAllFrames(); doc->layout(); doc->updateResizeHandles( ); doc->repaintAllViews(); } - KWRemoveColumnCommand::KWRemoveColumnCommand( const QString &name, KWTableFrameSet * _table, int _col ): KNamedCommand(name), m_pTable(_table), + m_rc(new RemovedColumn()), m_colPos(_col) { Q_ASSERT(m_pTable); } +KWRemoveColumnCommand::~KWRemoveColumnCommand() +{ + delete m_rc; +} + void KWRemoveColumnCommand::execute() { kdDebug() << "KWRemoveColumnCommand::execute" << endl; KWDocument * doc = m_pTable->kWordDocument(); doc->terminateEditing(m_pTable); - m_ListFrameSet.clear(); - m_copyFrame.clear(); - for ( unsigned int i = 0; i < m_pTable->getNumCells(); i++ ) - { - KWTableFrameSet::Cell *cell=static_cast(m_pTable->getCell( i )); - if(cell->firstCol() == m_colPos) - { - m_ListFrameSet.append(cell); - m_copyFrame.append(cell->frame(0)->getCopy()); - } - } - - m_pTable->deleteCol( m_colPos); + m_pTable->deleteCol( m_colPos, *m_rc); doc->frameSelectedChanged(); doc->updateAllFrames(); doc->layout(); @@ -1393,7 +1381,7 @@ void KWRemoveColumnCommand::unexecute() { kdDebug() << "KWRemoveColumnCommand::unexecute" << endl; KWDocument * doc = m_pTable->kWordDocument(); - m_pTable->insertCol( m_colPos,m_ListFrameSet,m_copyFrame); + m_pTable->reInsertCol(*m_rc); doc->updateAllFrames(); doc->layout(); doc->updateResizeHandles( ); diff -uNp --exclude-from=/home/carl/kde-devel/.diffignore kword/kwcommand.h kword-m_cells/kwcommand.h --- kword/kwcommand.h 2003-06-08 01:40:04.000000000 +1000 +++ kword-m_cells/kwcommand.h 2003-06-08 12:50:54.000000000 +1000 @@ -36,6 +36,8 @@ class KWFrameSet; class KWTableStyle; class KWTableTemplate; class KWTableFrameSet; +class RemovedRow; +class RemovedColumn; class KWPartFrameSet; class KWDocument; class KoCustomVariable; @@ -491,16 +493,17 @@ class KWInsertColumnCommand : public KNa public: /* for the last parameter, _maxRight, you should pass the maximum offset that the table can use at its right (normally m_maxRight - m_pTable->boundingRect().left())*/ KWInsertColumnCommand( const QString &name, KWTableFrameSet * _table, int _pos, double _maxRight); - ~KWInsertColumnCommand() {} + ~KWInsertColumnCommand(); void execute(); void unexecute(); protected: KWTableFrameSet *m_pTable; - QPtrList m_ListFrameSet; + RemovedColumn *m_rc; unsigned int m_colPos; double m_maxRight; // this is the maximum x of the right part of the table (used so that the table does no go off the page) double m_oldWidth; // will be 0 after execute() if the width of the table was not changed by the operation + bool m_inserted; }; @@ -511,14 +514,15 @@ class KWInsertRowCommand : public KNamed { public: KWInsertRowCommand( const QString &name, KWTableFrameSet * _table, int _pos); - ~KWInsertRowCommand() {} + ~KWInsertRowCommand(); void execute(); void unexecute(); protected: KWTableFrameSet *m_pTable; - QPtrList m_ListFrameSet; + RemovedRow *m_rr; unsigned int m_rowPos; + bool m_inserted; }; /** @@ -528,18 +532,16 @@ class KWRemoveRowCommand : public KNamed { public: KWRemoveRowCommand( const QString &name, KWTableFrameSet * _table, int _pos); - ~KWRemoveRowCommand() {} + ~KWRemoveRowCommand(); void execute(); void unexecute(); protected: KWTableFrameSet *m_pTable; - QPtrList m_ListFrameSet; - QPtrList m_copyFrame; - unsigned int m_rowPos; + RemovedRow *m_rr; + uint m_rowPos; }; - /** * Command created when removing a column */ @@ -547,15 +549,14 @@ class KWRemoveColumnCommand : public KNa { public: KWRemoveColumnCommand( const QString &name, KWTableFrameSet * _table, int _pos); - ~KWRemoveColumnCommand() {} + ~KWRemoveColumnCommand(); void execute(); void unexecute(); protected: KWTableFrameSet *m_pTable; - QPtrList m_ListFrameSet; - QPtrList m_copyFrame; - unsigned int m_colPos; + RemovedColumn *m_rc; + uint m_colPos; }; /** diff -uNp --exclude-from=/home/carl/kde-devel/.diffignore kword/KWordTableFrameSetIface.cc kword-m_cells/KWordTableFrameSetIface.cc --- kword/KWordTableFrameSetIface.cc 2003-05-24 19:33:52.000000000 +1000 +++ kword-m_cells/KWordTableFrameSetIface.cc 2003-06-08 12:41:45.000000000 +1000 @@ -61,10 +61,15 @@ void KWordTableFrameSetIface::deselectAl DCOPRef KWordTableFrameSetIface::getCell( int pos ) { - if( pos>=(int)m_table->getNumCells()) + // This method now sucks + KWTableFrameSet::TableIter i(m_table); + int p = 0; + for(; i && p <= pos; ++i,++p) + if( ! i.current() ) return DCOPRef(); + return DCOPRef( kapp->dcopClient()->appId(), - m_table->getCell(pos)->dcopObject()->objId() ); + i->dcopObject()->objId() ); } DCOPRef KWordTableFrameSetIface::getCell( uint row, uint col ) diff -uNp --exclude-from=/home/carl/kde-devel/.diffignore kword/KWordViewIface.cc kword-m_cells/KWordViewIface.cc --- kword/KWordViewIface.cc 2003-05-25 21:45:47.000000000 +1000 +++ kword-m_cells/KWordViewIface.cc 2003-06-08 15:49:06.000000000 +1000 @@ -245,6 +245,11 @@ void KWordViewIface::tableSplitCells() view->tableSplitCells(); } +void KWordViewIface::tableSplitCells(uint rows, uint cols) +{ + view->tableSplitCells(cols, rows); +} + void KWordViewIface::tableUngroupTable() { view->tableUngroupTable(); diff -uNp --exclude-from=/home/carl/kde-devel/.diffignore kword/KWordViewIface.h kword-m_cells/KWordViewIface.h --- kword/KWordViewIface.h 2003-05-25 21:45:47.000000000 +1000 +++ kword-m_cells/KWordViewIface.h 2003-06-08 15:22:54.000000000 +1000 @@ -59,6 +59,7 @@ k_dcop: virtual int tableDeleteCol(uint col); virtual void tableJoinCells(); virtual void tableSplitCells(); + virtual void tableSplitCells(uint rows, uint cols); virtual void tableUngroupTable(); virtual void insertPicture(); diff -uNp --exclude-from=/home/carl/kde-devel/.diffignore kword/kwtableframeset.cc kword-m_cells/kwtableframeset.cc --- kword/kwtableframeset.cc 2003-05-18 21:41:43.000000000 +1000 +++ kword-m_cells/kwtableframeset.cc 2003-06-08 16:36:36.000000000 +1000 @@ -43,13 +43,11 @@ DESCRIPTION KWTableFrameSet::KWTableFrameSet( KWDocument *doc, const QString & name ) : KWFrameSet( doc ) { - m_rows = 0; + m_rows = m_cols = m_nr_cells = 0; m_name = QString::null; m_showHeaderOnAllPages = true; m_hasTmpHeaders = false; m_active = true; - m_cells.setAutoDelete( true ); - m_rowArray.setAutoDelete( true ); frames.setAutoDelete(false); //m_anchor = 0L; if ( name.isEmpty() ) @@ -73,6 +71,7 @@ KWordFrameSetIface* KWTableFrameSet::dco return m_dcop; } + KWFrameSetEdit * KWTableFrameSet::createFrameSetEdit( KWCanvas * canvas ) { return new KWTableFrameSetEdit( this, canvas ); @@ -80,14 +79,12 @@ KWFrameSetEdit * KWTableFrameSet::create void KWTableFrameSet::updateFrames( int flags ) { - if(m_cells.count()==0) - return; - for(QPtrListIterator c(m_cells); c.current(); ++c) + for(TableIter c(this); c; ++c) c.current()->updateFrames( flags ); if ( isFloating() ) { KWAnchor * anchor = findAnchor( 0 ); if ( anchor ) - anchor->resize(); + anchor->resize(); } KWFrameSet::updateFrames( flags ); @@ -157,20 +154,11 @@ void KWTableFrameSet::deleteAnchors() deleteAnchor( anchor ); } -void KWTableFrameSet::addCell( Cell *cell ) -{ - unsigned int i = 0; - - // Find the insertion point in the list. - while ( i < m_cells.count() && m_cells.at( i )->isAboveOrLeftOf( cell->firstRow(), cell->firstCol() ) ) - ++i; - m_cells.insert( i, cell ); - addCellToArray( cell ); // temporarily moved to another method -} -void KWTableFrameSet::addCellToArray( Cell* cell ) // called add but also used to 'update' +void KWTableFrameSet::addCell( Cell* cell ) // called add but also used to 'update' { m_rows = QMAX( cell->rowAfter(), m_rows ); + m_cols = QMAX( cell->colAfter(), m_cols ); if ( m_rowArray.size() < cell->rowAfter() ) m_rowArray.resize( cell->rowAfter() ); @@ -184,11 +172,51 @@ void KWTableFrameSet::addCellToArray( Ce void KWTableFrameSet::removeCell( Cell* cell ) { - // m_cells handling not done here - // the point is to get rid of it in the long run for ( uint row = cell->firstRow() ; row < cell->rowAfter(); ++row ) m_rowArray[ row ]->removeCell( cell ); } + +void KWTableFrameSet::insertRowVector(uint index, Row *r) +{ + if(m_rowArray.size() < m_rowArray.count() + 1) + m_rowArray.resize(m_rowArray.count() + 1); + + for(uint i = m_rowArray.count(); i > index; i--) + m_rowArray.insert(i, m_rowArray[i-1]); + + m_rowArray.insert(index, r); +} + +/* + * Inserts a new (empty) element into each row vector. + * Elements in a row vector after index are moved back. + */ +void KWTableFrameSet::insertEmptyColumn(uint index) +{ + for(uint i = 0; i < m_rowArray.count(); ++i) { + Row *r = m_rowArray[i]; + if(r->m_cellArray.size() < m_cols + 1) + r->m_cellArray.resize(m_cols + 1); + for(int j = m_cols - 1; j >= (int)index; --j) + r->m_cellArray.insert(j + 1, r->m_cellArray[j]); + r->m_cellArray.insert(index, 0); + } +} + +KWTableFrameSet::Row* +KWTableFrameSet::removeRowVector(uint index) +{ + Q_ASSERT(index < m_rowArray.count() ); + Row *ret = m_rowArray.at(index); + Row *r; + for(uint i = index; i < m_rowArray.size() - 1; ++i){ + r = m_rowArray.at(i+1); + m_rowArray.remove(i+1); + m_rowArray.insert(i,r); + } + return ret; +} + KoRect KWTableFrameSet::boundingRect() { return KoRect(m_colPositions[0], // left @@ -228,10 +256,11 @@ KWTableFrameSet::Cell *KWTableFrameSet:: if ( cell ) return cell; } - kdWarning() << getName() << " getCell " << row << "," << col << " => returning 0!" << kdBacktrace( 3 ) << endl; -#ifndef NDEBUG - printArrayDebug(); -#endif +// kdWarning() << getName() << " getCell " << row << "," << col << " => returning 0!" << kdBacktrace( 3 ) << endl; +//#ifndef NDEBUG +// validate(); +// printArrayDebug(); +//#endif return 0L; } @@ -244,7 +273,6 @@ KWTableFrameSet::Cell *KWTableFrameSet:: void KWTableFrameSet::recalcCols(int _col,int _row) { //kdDebug(32004) << "KWTableFrameSet::recalcCols" << endl; - if(m_cells.isEmpty()) return; // assertion // check/set sizes of frames unsigned int row=0,col=0; @@ -279,7 +307,7 @@ void KWTableFrameSet::recalcCols(int _co difference = difference2; } - redrawFromCol=getCols(); // possible reposition col starting with this one, done in recalcRows + m_redrawFromCol=getCols(); // possible reposition col starting with this one, done in recalcRows if(difference!=0) { double last=col==0?0:m_colPositions[col-1]; for(unsigned int i=col; i < m_colPositions.count(); i++) { @@ -291,8 +319,8 @@ void KWTableFrameSet::recalcCols(int _co } last=colPos; } - redrawFromCol=col; - if(col>0) redrawFromCol--; + m_redrawFromCol=col; + if(col>0) m_redrawFromCol--; //if(activeCell) activeCell->frame(0)->setMinFrameHeight(0); } @@ -303,8 +331,6 @@ void KWTableFrameSet::recalcRows(int _co kdDebug(32004) << getName() << " KWTableFrameSet::recalcRows ("<< _col <<"," << _row << ")" << endl; //for(unsigned int i=0; i < m_rowPositions.count() ; i++) kdDebug(32004) << "row: " << i << " = " << m_rowPositions[i] << endl; - Q_ASSERT( !m_cells.isEmpty() ); - // check/set sizes of frames unsigned int row=0,col=0; if(_col!=-1 && _row!=-1) @@ -586,13 +612,14 @@ void KWTableFrameSet::recalcRows(int _co //kdDebug () << "Repositioning from row : " << fromRow << " until: " << untilRow << endl; //kdDebug () << "Repositioning from col > " << redrawFromCol << endl; // do positioning. - Cell *cell; + //Cell *cell; //bool setMinFrameSize= activeCell->frame(0)->isSelected(); - for(cell=m_cells.first();cell;cell=m_cells.next()) { - if((cell->rowAfter() > fromRow && cell->firstRow() < untilRow) || cell->colAfter() > redrawFromCol) + + for(TableIter cell(this); cell; ++cell) { + if((cell->rowAfter() > fromRow && cell->firstRow() < untilRow) || cell->colAfter() > m_redrawFromCol) position(cell, (cell==activeCell && cell->frame(0)->isSelected())); } - redrawFromCol=getCols(); + m_redrawFromCol = getCols(); // check if any rowPosition entries are unused @@ -602,10 +629,9 @@ void KWTableFrameSet::recalcRows(int _co for(unsigned int i=0; i < top; rows[i++]=0); // fill hash with data - for (cell = m_cells.first(); cell; cell = m_cells.next()) { - rows[cell->firstRow()]+=1; + for(TableIter i(this); i; ++i) { + rows[i->firstRow()] += 1; } - // check if some entries have stayed unused. unsigned int counter=top; int adjustment=m_pageBoundaries.count()-1; @@ -618,7 +644,7 @@ void KWTableFrameSet::recalcRows(int _co kdDebug() << k_funcinfo << "no rows at counter=" << counter << " -> erasing" << endl; m_rows--; m_rowPositions.erase(m_rowPositions.at(counter+(adjustment>0?adjustment:0))); - for (cell = m_cells.first(); cell; cell = m_cells.next()) { + for (TableIter cell(this); cell; ++cell) { if(cell->firstRow() < counter && cell->rowAfter() > counter) cell->setRowSpan(cell->rowSpan()-1); if(cell->firstRow() > counter) @@ -636,12 +662,12 @@ void KWTableFrameSet::recalcRows(int _co } while(counter!=0); - redrawFromCol=0; - for(cell=m_cells.first();cell;cell=m_cells.next()) { - if((cell->rowAfter() > fromRow && cell->firstRow() < untilRow) || cell->colAfter() > redrawFromCol) + m_redrawFromCol = 0; + for (TableIter cell(this); cell; ++cell) { + if((cell->rowAfter() > fromRow && cell->firstRow() < untilRow) || cell->colAfter() > m_redrawFromCol) position(cell); } - redrawFromCol=getCols(); + m_redrawFromCol = getCols(); kdDebug(32004) << getName() << " KWTableFrameSet::recalcRows done" << endl; updateFrames(); } @@ -679,9 +705,9 @@ void KWTableFrameSet::resizeColumn( unsi { kdDebug() << k_funcinfo << col << "," << x << endl; m_colPositions[ col ] = x; + // move all cells right of 'col' - for ( unsigned int i = 0; i < m_cells.count(); i++ ) { - Cell *cell = m_cells.at(i); + for (TableIter cell(this); cell; ++cell) { if ( cell->colAfter() >= col ) { position(cell); } @@ -694,8 +720,7 @@ void KWTableFrameSet::resizeRow( unsigne kdDebug() << k_funcinfo << row << "," << y << endl; m_rowPositions[ row ] = y; // move all cells under 'row' - for ( unsigned int i = 0; i < m_cells.count(); i++ ) { - Cell *cell = m_cells.at(i); + for (TableIter cell(this); cell; ++cell) { if ( cell->rowAfter() >= row ) { position(cell); } @@ -726,7 +751,7 @@ void KWTableFrameSet::setBoundingRect( K // Column positions.. m_colPositions.clear(); unsigned int cols=0; - for(QPtrListIterator c(m_cells); c.current(); ++c) + for (TableIter c(this); c; ++c) cols = QMAX(cols, c.current()->colAfter()); double colWidth = rect.width() / cols; if ( widthMode == TblAuto ) { @@ -750,19 +775,25 @@ void KWTableFrameSet::setBoundingRect( K m_rowPositions.append(rect.y() + rowHeight * i); } - Cell *theCell; double oneMm = MM_TO_POINT( 1.0 ); - for(theCell=m_cells.first(); theCell; theCell=m_cells.next()) { - KWFrame *frame = theCell->frame(0); + for (TableIter cell(this); cell; ++cell) { + KWFrame *frame = cell->frame(0); frame->setBLeft( oneMm ); frame->setBRight( oneMm ); frame->setBTop( oneMm ); frame->setBBottom( oneMm ); frame->setNewFrameBehavior( KWFrame::NoFollowup ); - position(theCell, true); + position(cell, true); } } +/** + Adjusts the size of the cell frames. + It computes the sizes based on: + (1) The values in the m_colPositions and m_rowPositions arrays. + (2) The width of the Cell borders. + +*/ void KWTableFrameSet::position( Cell *theCell, bool setMinFrameHeight ) { if(!theCell->frame(0)) { // sanity check. kdDebug(32004) << "errorous table cell!! row:" << theCell->firstRow() @@ -799,6 +830,13 @@ void KWTableFrameSet::position( Cell *th theCell->setVisible(true); } +/** + Returns a double value from m_rowPositions. This is either the bottom + or top position of the row of cells @p row. Note that you cannot index + directly into m_rowPositions from a row value obtained from a cell, + eg cell->firstRow(), because of the extra elements in m_rowPositions when + the table spans multiple pages. +*/ double KWTableFrameSet::getPositionOfRow( unsigned int row, bool bottom ) { unsigned int adjustment=0; QValueList::iterator pageBound = m_pageBoundaries.begin(); @@ -839,8 +877,7 @@ void KWTableFrameSet::moveBy( double dx, } if(redraw) { - Cell *cell; - for(cell=m_cells.first();cell;cell=m_cells.next()) + for(TableIter cell(this);cell;++cell) position(cell); } } @@ -863,8 +900,8 @@ void KWTableFrameSet::selectCol(uint col void KWTableFrameSet::deselectAll() { - for ( unsigned int i = 0; i < m_cells.count(); i++ ) - m_cells.at( i )->frame( 0 )->setSelected( false ); + for (TableIter i(this) ; i; ++i ) + i->frame( 0 )->setSelected( false ); } void KWTableFrameSet::refreshSelectedCell() @@ -913,8 +950,7 @@ void KWTableFrameSet::selectUntil( Cell fromCol = fromCol^toCol; } - for ( unsigned int i = 0; i < m_cells.count(); i++ ) { - cell = m_cells.at(i); + for ( TableIter cell(this); cell; ++cell ) { // check if cell falls completely in square. unsigned int row = cell->lastRow(); unsigned int col = cell->lastCol(); @@ -941,52 +977,53 @@ void KWTableFrameSet::selectUntil( Cell stay unchanged (and false is returned). */ bool KWTableFrameSet::isOneSelected(unsigned int &row, unsigned int &col) { - int selectedCell=-1; - for ( unsigned int i = 0; i < m_cells.count(); i++ ) { - if(m_cells.at(i)->frame(0)->isSelected()) { - if(selectedCell==-1) - selectedCell=i; - else - selectedCell=m_cells.count()+1; + Cell *selected = 0; + bool one = false; + for ( TableIter cell(this); cell; ++cell) { + if(cell->frame(0)->isSelected()) { + if(one) + selected = 0; + else{ + selected = (Cell*) cell; + one = true; + } } } - if(selectedCell>=0 && selectedCell<= static_cast (m_cells.count())) { - row=m_cells.at(selectedCell)->firstRow(); - col=m_cells.at(selectedCell)->firstCol(); + if(selected) { + row = selected->firstRow(); + col = selected->firstCol(); return true; } return false; } bool KWTableFrameSet::isRowSelected(uint row) { - Q_ASSERT(row <= getRows()); + Q_ASSERT(row < getRows()); + Row *r = m_rowArray[row]; + // if just one cell of the row is not selected, the row is not selected - for ( uint i = 0; i < m_cells.count(); i++ ) { - if (!m_cells.at( i )->frame( 0 )->isSelected()) { - if (m_cells.at( i )->firstRow() == row) - { - kdDebug() << "row " << row << " row is not selected" << endl; + for ( uint i = 0; i < r->size(); i++ ) { + if ( !((*r)[i]->frame(0)->isSelected()) ) { +// kdDebug() << "row " << row << " row is not selected" << endl; return false; - } } } - kdDebug() << "row " << row << " row is selected" << endl; +// kdDebug() << "row " << row << " row is selected" << endl; return true; } -bool KWTableFrameSet::isColSelected(uint column) { - Q_ASSERT(column <= getCols()); +bool KWTableFrameSet::isColSelected(uint col) { + Q_ASSERT(col <= getCols()); + Row *r; // if just one cell of the col is not selected, the col is not selected - for ( uint i = 0; i < m_cells.count(); i++ ) { - if (!m_cells.at( i )->frame( 0 )->isSelected()) { - if (m_cells.at( i )->firstCol() == column) - { - kdDebug() << "column " << column << " column is not selected" << endl; - return false; - } + for ( uint i = 0; i < getRows(); i++ ) { + r = m_rowArray[i]; + if ( !((*r)[col]->frame( 0 )->isSelected()) ) { +// kdDebug() << "column " << col << " column is not selected" << endl; + return false; } } - kdDebug() << "column " << column << " column is selected" << endl; +// kdDebug() << "column " << col << " column is selected" << endl; return true; } @@ -1008,48 +1045,143 @@ bool KWTableFrameSet::isColsSelected() { bool KWTableFrameSet::getFirstSelected( unsigned int &row, unsigned int &col ) { - for ( unsigned int i = 0; i < m_cells.count(); i++ ) { - if (m_cells.at( i )->frame( 0 )->isSelected()) { - row = m_cells.at( i )->firstRow(); - col = m_cells.at( i )->firstCol(); + for ( TableIter i(this); i ; ++i ) { + if (i->frame( 0 )->isSelected()) { + row = i->firstRow(); + col = i->firstCol(); return true; } } return false; } -void KWTableFrameSet::insertRow( unsigned int newRowNumber,QPtrList redoFrameset, QPtrList redoFrame, - bool recalc, bool isAHeader ) { +/* Delete all cells that are completely in this row. */ +void KWTableFrameSet::deleteRow( unsigned int row, RemovedRow &rr, bool _recalc) +{ + Q_ASSERT(row < m_rowArray.size()); + const unsigned int rowspan=1; + + double height= getPositionOfRow(row+rowspan-1,true) - getPositionOfRow(row); + QValueList::iterator tmp = m_rowPositions.at(row+rowspan); + tmp=m_rowPositions.erase(tmp); + while(tmp!=m_rowPositions.end()) { + (*tmp)= (*tmp)-height; + tmp++; + } + + rr.m_index = row; + rr.m_rowHeight = height; + rr.m_row = m_rowArray[row]; + + // move/delete cells. + for ( TableIter cell(this); cell; ++cell ) { + if ( row >= cell->firstRow() && row < cell->rowAfter()) { // cell is indeed in row + if(cell->rowSpan() == 1) { // cell is wholly contained within row + frames.remove( cell->frame(0) ); + } else { // make cell span rowspan less rows + cell->setRowSpan(cell->rowSpan()-rowspan); + position(cell); + } + + } else if ( cell->firstRow() > row ) { + // move cell up + cell->setFirstRow( cell->firstRow() - rowspan ); + position(cell); + } + } + + removeRowVector(row); + m_rows -= rowspan; + m_rowArray.resize( m_rows ); + printArrayDebug(); + validate(); + + if ( _recalc ) + recalcRows(); +} + +void KWTableFrameSet::reInsertRow(RemovedRow &rr) +{ + uint row = rr.index(); + Row *r = rr.row(); + uint rlen = r->count(); + + // adjust cell positions & sizes + for(MarkedIterator cell(this); cell; ++cell) { + + if ( cell->firstRow() < row && cell->lastRow() >= row ){ // cell is indeed in row + cell->setRowSpan(cell->rowSpan() + 1); + } + else if(r->m_cellArray[cell->firstCol()] == cell.current()) { + cell->setRowSpan(cell->rowSpan() + 1); + } + else if ( cell->firstRow() >= row ) { + // move cell down + cell->setFirstRow( cell->firstRow() + 1); + } + } + + // put back frames that were removed + for(uint i = 0; i < rlen; i++){ + if( frames.findRef((*r)[i]->frame(0)) == -1 ) + frames.append( (*r)[i]->frame(0) ); + } + + // adjust row positions (ignores page boundaries!)a + if(row == m_rows) { //reinserting at bottom of table + double d = m_rowPositions.last() + rr.height(); + m_rowPositions.append(d); + } + else { + QValueList::iterator top = m_rowPositions.at(row); + QValueList::iterator i = m_rowPositions.at(row+1); + i = m_rowPositions.insert(i, *top + rr.height()); + i++; + for(; i != m_rowPositions.end(); ++i) { + *i = *i+ rr.height(); + } + } + + // reinsert row into array + m_rows++; + insertRowVector(rr.index(), rr.takeRow()); + + // don't actually have to visit all the cells, this could be optimised + for(TableIter i(this); i ; ++i) + position(i.current()); + + validate(); +} + +void KWTableFrameSet::insertNewRow( uint idx, bool recalc, bool _removeable) +{ - unsigned int copyFromRow = newRowNumber==0?0:newRowNumber-1; - if(newRowNumber==0) + (void) _removeable; // unused parameter + unsigned int copyFromRow = idx==0?0:idx-1; + if(idx==0) copyFromRow=1; + Row *copyRow = m_rowArray[copyFromRow]; + uint new_rows = m_rows + 1; // What height to use for the new row - double height = 0; - if(redoFrame.isEmpty()) - height = getPositionOfRow(copyFromRow,true) - getPositionOfRow(copyFromRow); - else { - KWFrame *f = redoFrame.at(0); - height = f->height() + f->topBorder().width() + f->bottomBorder().width();; - } + double height = getPositionOfRow(copyFromRow,true) - getPositionOfRow(copyFromRow); // Calculate offset in QValueList because of page breaks. unsigned int adjustment=0; unsigned int untilRow=m_rows; QValueList::iterator pageBound = m_pageBoundaries.begin(); - while(pageBound != m_pageBoundaries.end() && (*pageBound) <= newRowNumber) { + while(pageBound != m_pageBoundaries.end() && (*pageBound) <= idx) { // Find out how many pages we allready had. adjustment++; pageBound++; } // Move all rows down from newRow to bottom of page - QValueList::iterator tmp = m_rowPositions.at(newRowNumber); + QValueList::iterator tmp = m_rowPositions.at(idx); double newPos = *tmp + height; tmp++; m_rowPositions.insert(tmp, newPos); - for(unsigned int i=newRowNumber+adjustment+2; i < m_rowPositions.count(); i++) { + for(unsigned int i=idx+adjustment+2; i < m_rowPositions.count(); i++) { double &rowPos = m_rowPositions[i]; kdDebug(32004) << "adjusting " << rowPos << " -> " << rowPos + height << endl; rowPos = rowPos + height; @@ -1059,268 +1191,225 @@ void KWTableFrameSet::insertRow( unsigne } } - // Position all changed cells. - unsigned int newRows=++m_rows; - for ( unsigned int i = 0; i < m_cells.count(); i++ ) { - Cell *cell = m_cells.at(i); - if ( cell->firstRow() >= newRowNumber ) { // move all cells beneath the new row. +// printArrayDebug(); + + for ( MarkedIterator cell(this); cell; ++cell) { + if ( cell->firstRow() >= idx ) { // move all cells beneath the new row. cell->setFirstRow(cell->firstRow()+1); - position(cell); } } - unsigned int i =0; - double oneMm = MM_TO_POINT( 1.0 ); + insertRowVector(idx, new Row); + + unsigned int i = 0; while(i < getCols()) { - KWFrame *theFrame = 0L; - if(redoFrame.isEmpty()) - { - theFrame=new KWFrame(0L, 1, 1, 100, 20, KWFrame::RA_NO); // use dummy values here... - theFrame->setFrameBehavior(KWFrame::AutoExtendFrame); - theFrame->setNewFrameBehavior(KWFrame::NoFollowup); - // copying the zorder of the neighbouring cell in the table : - theFrame->setZOrder(getCell(newRowNumber+(newRowNumber==0?1:-1), i)->frame(0)->zOrder()); - theFrame->setMinFrameHeight(theFrame->height()); - } - else - { - if(igetCopy(); - } - Cell *newCell=0L; - if(redoFrameset.isEmpty()) - newCell=new Cell( this, newRowNumber, i, QString::null ); - else - { - if( i (redoFrameset.at(i)); - addCell( newCell ); + if(idx != 0 && (idx != m_rows)) { + Cell *c = getCell(idx - 1, i); + if( c == getCell(idx + 1, i) ) { + m_rowArray[idx]->addCell(c); + c->setRowSpan(c->rowSpan() + 1); + i += c->colSpan(); + continue; // don't need to make a new cell } - else - { - newCell = getCell(newRowNumber-1,i); - newCell->setRowSpan(newCell->rowSpan() + 1); - addCellToArray(newCell); - continue; - } - } + } + KWFrame *theFrame = new KWFrame(copyRow->m_cellArray[i]->frame(0)); + Cell *newCell=new Cell( this, idx, i, QString::null ); newCell->setColSpan( getCell(copyFromRow,i)->colSpan() ); - newCell->setIsRemoveableHeader( isAHeader ); + addCell(newCell); newCell->addFrame( theFrame, false ); - theFrame->setBLeft( oneMm ); - theFrame->setBRight( oneMm ); - theFrame->setBTop( oneMm ); - theFrame->setBBottom( oneMm ); position(newCell); - i += newCell->colSpan(); - } + } - m_rows = newRows; + // Position all changed cells. + + m_rows = new_rows; + validate(); if ( recalc ) finalize(); } -void KWTableFrameSet::insertCol( unsigned int newColNumber,QPtrList redoFrameset, QPtrListredoFrame, double width /* =KWTableFrameSet::ms_defaultWidth.*/ ) { - width=QMAX(width,s_minFrameWidth); - - if(! redoFrame.isEmpty()) { - KWFrame *f = redoFrame.at(0); - width=f->width() + f->leftBorder().width() + f->rightBorder().width(); +void KWTableFrameSet::deleteCol(uint col, RemovedColumn &rc) +{ + // keep these values in case we have to put it back + if(!rc.m_initialized) { + rc.m_index = col; + rc.m_width = m_colPositions[col+1] - m_colPositions[col]; } - QValueList::iterator tmp = m_colPositions.at(newColNumber); - - tmp=m_colPositions.insert(tmp, *tmp); - tmp++; - while(tmp!=m_colPositions.end()) { - (*tmp)= (*tmp)+width; + // move the colomn positions + QValueList::iterator tmp = m_colPositions.at(col+1); + tmp = m_colPositions.erase(tmp); + while(tmp != m_colPositions.end()) { + (*tmp) = (*tmp) - rc.m_width; tmp++; } - for ( unsigned int i = 0; i < m_cells.count(); i++ ) { - Cell *cell = m_cells.at(i); - if ( cell->firstCol() >= newColNumber) { // move all cells right of the new col. - cell->setFirstCol(cell->firstCol() + 1); - position(cell); - } - } + // remove cells that are wholy in this column, + // otherwise reduce rowspan. pointers to all cells + // are kept in the RemovedColumn + CheckedIter iter(this); + for(uint i = 0; i < m_rows; ++i) { + Cell *cell = getCell(i, col); + + if(!rc.m_initialized) { + rc.m_column.append(cell); + rc.m_removed.append(cell->colSpan() == 1); + } - for( unsigned int i = 0; i < getRows(); i++ ) { - int rows; - Cell *cell; - if(newColNumber > 0 ) { - cell = getCell(i, newColNumber-1); - if(cell->colAfter() > newColNumber) { - // cell overlaps the new column - cell->setColSpan(cell->colSpan() + 1); - continue; - } - rows = cell->rowSpan(); - } else { - rows = 1; - cell = getCell(i, newColNumber+1); - } - Cell *newCell=0L; - if(redoFrameset.isEmpty()) - newCell = new Cell( this, i, newColNumber, QString::null ); - else - { - if( i (redoFrameset.at(i)); - addCell( newCell ); + if(cell->colSpan() == 1) { // lets remove it + if(cell->firstRow() == i) { + frames.remove( cell->frame(0) ); + m_nr_cells--; } - else - { - newCell =getCell(i,newColNumber-1); - newCell->setColSpan(newCell->colSpan() + 1); - addCellToArray(newCell); - continue; + m_rowArray[i]->m_cellArray.insert(col, 0); + } + else { // make cell span 1 less column + if(cell->firstRow() == i) { + cell->setColSpan( cell->colSpan() - 1 ); + position(cell); } } - KWFrame *theFrame = 0L; - if(redoFrame.isEmpty()) - { - theFrame=new KWFrame(newCell, 1, 1, width, 20, KWFrame::RA_NO ); // dummy values.. - theFrame->setFrameBehavior(KWFrame::AutoExtendFrame); - theFrame->setNewFrameBehavior(KWFrame::NoFollowup); - // copying the zorder of the neighbouring cell in the table : - theFrame->setZOrder(getCell(i, newColNumber+(newColNumber==0?1:-1))->frame(0)->zOrder()); - theFrame->setMinFrameHeight(theFrame->height()); - } - else - { - theFrame=redoFrame.at(i)->getCopy(); - } - newCell->addFrame( theFrame,false ); - if(cell->rowSpan() > 1) { - newCell->setRowSpan(cell->rowSpan()); - i += cell->rowSpan() - 1; + } + + // adjust cells in a later column + for(; iter; ++iter) { + if (iter->firstCol() > col ) { + iter->setFirstCol( iter->firstCol() - 1); + position(iter.current()); } - position(newCell); } - finalize(); + + // move pointers in 2d array back one column to occupy + // removed column + for(uint i = 0; i < m_rows; i++) { + for(uint j = col + 1; j < m_cols; j++) + m_rowArray[i]->m_cellArray.insert(j-1, m_rowArray[i]->m_cellArray[j]); + } + m_cols--; + rc.m_initialized = true; + + printArrayDebug(); + validate(); + recalcCols(); + recalcRows(); } -/* Delete all cells that are completely in this row. */ -void KWTableFrameSet::deleteRow( unsigned int row, bool _recalc ) +void KWTableFrameSet::reInsertCol(RemovedColumn &rc) { - unsigned int rowspan=0; - // I want to know the amount of the row(s) I am removing. - // ## This code makes no sense. _One_ vertically merged cell, and the whole row below get removed? (DF) - for (unsigned int rs=1; rs < m_rows && rowspan == 0; rs++) { - for ( unsigned int i = 0; i < m_cells.count(); i++ ) { - if(m_cells.at(i)->firstRow() == row && m_cells.at(i)->rowSpan()==rs) { - rowspan=rs; - break; - } - } - } + QValueList::iterator tmp = m_colPositions.at(rc.m_index); - double height= getPositionOfRow(row+rowspan-1,true) - getPositionOfRow(row); - QValueList::iterator tmp = m_rowPositions.at(row+rowspan); - tmp=m_rowPositions.erase(tmp); - while(tmp!=m_rowPositions.end()) { - (*tmp)= (*tmp)-height; + tmp = m_colPositions.insert(tmp, *tmp); + tmp++; + while(tmp != m_colPositions.end()) { + (*tmp) = (*tmp) + rc.m_width; tmp++; } - // move/delete cells. - for ( unsigned int i = 0; i < m_cells.count(); i++ ) { - Cell *cell = m_cells.at(i); - if ( row >= cell->firstRow() && row < cell->rowAfter()) { // cell is indeed in row - if(cell->rowSpan() == 1) { // lets remove it - frames.remove( cell->frame(0) ); - cell->delFrame( cell->frame(0) ); - removeCell( cell ); - m_cells.take(i); // doesn't delete cell (for undo/redo purposes) - i--; - } else { // make cell span rowspan less rows - cell->setRowSpan(cell->rowSpan()-rowspan); - position(cell); - } - } else if ( cell->firstRow()> row ) { - // move cell up - removeCell( cell ); - cell->setFirstRow( cell->firstRow() - rowspan ); - addCell( cell ); - position(cell); + printArrayDebug(); + + // if a cell starts after the column we are inserting, it + // must be moved to the right, except if it is going to + // occury the reinserted column also. + for ( MarkedIterator cell(this); cell ; ++cell ) { + if ( cell->firstCol() >= rc.m_index && + (rc.m_column.at(cell->firstRow()) != cell.current())) { + + cell->setFirstCol(cell->firstCol() + 1); } } - // now delete the last 'rowspan' lines - m_rows -= rowspan; - m_rowArray.resize( m_rows ); + insertEmptyColumn(rc.m_index); + m_cols++; - if ( _recalc ) - recalcRows(); -} + printArrayDebug(); -/* Delete all cells that are completely in this col. */ -void KWTableFrameSet::deleteCol( unsigned int col ) -{ - double width=0; - unsigned int colspan=1; - // I want to know the width of the col(s) I am removing. - for (unsigned int colspan=1; colspan < getCols() && width==0; colspan++) { - for ( unsigned int i = 0; i < m_cells.count(); i++ ) { - if(m_cells.at(i)->firstCol() == col && m_cells.at(i)->colSpan()==colspan) { - width=m_cells.at(i)->frame(0)->width(); - break; + for(uint i = 0; i < m_rows; ++i) { + bool removed = rc.m_removed[i]; + Cell *cell = rc.m_column.at(i); + if(i == cell->firstRow()) { + if(removed) { + cell->setColSpan(1); + frames.append(cell->frame(0)); + m_nr_cells++; } + else { + cell->setColSpan(cell->colSpan() + 1); + } + addCell(cell); } } - QValueList::iterator tmp = m_colPositions.at(col+1); - tmp=m_colPositions.erase(tmp); + printArrayDebug(); + + validate(); + finalize(); +} + +void KWTableFrameSet::insertNewCol( uint idx, double width) +{ + QValueList::iterator tmp = m_colPositions.at(idx); + + tmp = m_colPositions.insert(tmp, *tmp); + tmp++; while(tmp!=m_colPositions.end()) { - (*tmp)= (*tmp)-width; + (*tmp)= (*tmp)+width; tmp++; } - // move/delete cells. - for ( unsigned int i = 0; i < m_cells.count(); i++ ) { - Cell *cell = m_cells.at(i); - if ( col >= cell->firstCol() && col < cell->colAfter()) { // cell is indeed in col - if(cell->colSpan() == 1) { // lets remove it - frames.remove( cell->frame(0) ); - cell->delFrame( cell->frame(0)); - removeCell( cell ); - m_cells.take(i); // doesn't delete cell (for undo/redo purposes) - i--; - } else { // make cell span colspan less cols - cell->setColSpan( cell->colSpan() - colspan ); - position(cell); - } - } else if ( cell->firstCol() > col ) { - // move cell to the left - removeCell( cell ); - cell->setFirstCol( cell->firstCol() - colspan ); - addCell( cell ); - position(cell); + for ( MarkedIterator cell(this); cell ; ++cell ) { + if ( cell->firstCol() >= idx) { // move all cells right of the new col. + cell->setFirstCol(cell->firstCol() + 1); } } + insertEmptyColumn(idx); + m_cols++; + uint copyCol = (idx == 0) ? 1 : idx - 1 ; - recalcCols(); - recalcRows(); + // make the new cells + // note that the loop counter is mucked with in the loop! + for( unsigned int i = 0; i < getRows(); i++ ) { + + // can't break a cell in half, so if there is the same cell + // on both sides of inserted column, it occupies the new + // column as well + if(idx != 0 && (idx != m_cols -1)) { + Cell *c = getCell(i, idx - 1); + if( c == getCell(i, idx + 1) ) { +// m_rowArray[i]->m_cellArray.insert(idx, c); + c->setColSpan(c->colSpan() + 1); + addCell(c); + i += c->rowSpan() - 1; + continue; // don't need to make a new cell + } + } + + Cell *newCell = new Cell( this, i, idx, QString::null ); + KWFrame *theFrame = new KWFrame(getCell(i, copyCol)->frame(0)); + newCell->addFrame( theFrame, false ); + position(newCell); + m_nr_cells++; + } + validate(); + finalize(); } void KWTableFrameSet::ungroup() { - m_cells.setAutoDelete( false ); - m_cells.clear(); +// m_cells.setAutoDelete( false ); +// m_cells.clear(); + m_nr_cells = 0; m_active = false; } void KWTableFrameSet::group() { - m_cells.setAutoDelete( true ); - m_cells.clear(); +// m_cells.setAutoDelete( true ); +// m_cells.clear(); + m_nr_cells = 0; m_active = true; } @@ -1375,19 +1464,17 @@ KCommand *KWTableFrameSet::joinCells(uns listCopyFrame.append(cell->frame(0)->getCopy()); frames.remove( cell->frame(0) ); cell->delFrame( cell->frame(0)); - //removeCell(cell); - m_cells.take(m_cells.find(cell)); - // cell is not deleted (for undo/redo purposes...) } } } Q_ASSERT(firstCell); // update firstcell properties to reflect the merge - firstCell->setColSpan(colEnd - colBegin + 1); - firstCell->setRowSpan(rowEnd - rowBegin + 1); - addCellToArray(firstCell); + firstCell->setColSpan(colEnd-colBegin+1); + firstCell->setRowSpan(rowEnd-rowBegin+1); + addCell(firstCell); position(firstCell); + validate(); firstCell->frame(0)->updateResizeHandles(); m_doc->updateAllFrames(); // TODO: only fs->updateFrames() & m_doc->updateFramesOnTopOrBelow(pageNum) @@ -1399,6 +1486,7 @@ KCommand *KWTableFrameSet::splitCell(uns if(intoRows < 1 || intoCols < 1) return 0L; + kdDebug(32004) << "KWTableFrameSet::splitCell" << endl; unsigned int col, row; if(_col!=-1 && _row!=-1) { @@ -1411,7 +1499,9 @@ KCommand *KWTableFrameSet::splitCell(uns return 0L; } - Cell *cell = getCell(row,col); + printArrayDebug(); + + Cell *cell=getCell(row,col); int rowsDiff = intoRows - cell->rowSpan(); int colsDiff = ((int) intoCols) - cell->colSpan(); @@ -1431,7 +1521,15 @@ KCommand *KWTableFrameSet::splitCell(uns iRow=m_rowPositions.insert(iRow, newPos); } -//for(unsigned int i=0; i < m_rowPositions.count() ; kdDebug(32004) << "row " << i << ": " << m_rowPositions[i++] << endl); + // insert more rows into m_rowArray + for(int i = 0; i < rowsDiff; ++i) { + insertRowVector(row+i+1, new Row); + m_rows++; + } + + // m_rows += rowsDiff; + //for(unsigned int i=0; i < m_rowPositions.count() ; ++i) + // kdDebug(32004) << "row " << i << ": " << m_rowPositions[i] << endl); } if(colsDiff >0) { double width = (m_colPositions[col+1] - m_colPositions[col])/intoCols; @@ -1443,50 +1541,46 @@ KCommand *KWTableFrameSet::splitCell(uns iCol=m_colPositions.insert(iCol, newPos); } - //for(unsigned int i=0; i < m_colPositions.count() ; kdDebug(32004) << "col " << i << ": " << m_colPositions[i++] << endl); + for(int i = 0; i < colsDiff; i++) { + insertEmptyColumn(col+i+1); + m_cols++; + } + //for(unsigned int i=0; i < m_colPositions.count(); ++i) + // kdDebug(32004) << "col " << i << ": " << m_colPositions[i] << endl); + //m_cols += colsDiff; } - KWFrame *firstFrame = cell->frame(0); + printArrayDebug(); // adjust cellspan and rowspan on other cells. - for (unsigned int i=0; i< m_cells.count() ; i++) { - Cell *theCell = m_cells.at(i); - if(cell == theCell) continue; + for (CheckedIter i(this); i ; ++i) { + if(cell == i) continue; if(rowsDiff>0) { - if(row >= theCell->firstRow() && row < theCell->rowAfter()) - theCell->setRowSpan(theCell->rowSpan() + rowsDiff); - if(theCell->firstRow() > row) { - theCell->setFirstRow(theCell->firstRow() + rowsDiff); + if(row >= i->firstRow()&& row < i->firstRow()+ i->rowSpan()) + i->setRowSpan(i->rowSpan() + rowsDiff); + if(i->firstRow() > row) { + i->setFirstRow(i->firstRow() + rowsDiff); // theCell->frame(0)->setTop(theCell->frame(0)->top()+extraHeight); } } if(colsDiff>0) { - if(col >= theCell->firstCol() && col < theCell->colAfter()) - theCell->setColSpan(theCell->colSpan() + colsDiff); - if(theCell->firstCol() > col) - theCell->setFirstCol(theCell->firstCol() + colsDiff); + if(col >= i->firstCol() && col < i->colAfter()) + i->setColSpan(i->colSpan() + colsDiff); + if(i->firstCol() > col) + i->setFirstCol(i->firstCol() + colsDiff); } - /*if(extraHeight != 0 && theCell->firstRow() == row) { + /*if(extraHeight != 0 && theCell->firstRow()== row) { theCell->frame(0)->setHeight(theCell->frame(0)->height()+extraHeight); } */ if ( rowsDiff > 0 || colsDiff > 0 ) // something changed? - addCellToArray( theCell ); // update arrays + addCell( i ); // update arrays } - // set new row and col-span. Use intermediate ints otherwise we get strange results as the - // intermediate result could be negative (which goes wrong with unsigned ints) - int r = (cell->rowSpan() + 1) - intoRows; - if(r < 1) r=1; - cell->setRowSpan(r); - - int c = (cell->colSpan() + 1) - intoCols; - if(c < 1) c=1; - cell->setColSpan(c); + printArrayDebug(); - // If we created extra rows/cols, adjust the groupmanager counters. - if(rowsDiff > 0) m_rows += rowsDiff; int i=0; + KWFrame *firstFrame = cell->frame(0); // create new cells for (unsigned int y = 0; y < intoRows; y++) { for (unsigned int x = 0; x < intoCols; x++){ @@ -1498,13 +1592,10 @@ KCommand *KWTableFrameSet::splitCell(uns if(listFrameSet.isEmpty()) { lastFrameSet= new Cell( this, y + row, x + col ); - lastFrameSet->setRowSpan(1); - lastFrameSet->setColSpan(1); } else { lastFrameSet = static_cast (listFrameSet.at(i)); - addCell( lastFrameSet ); } KWFrame *theFrame=0L; @@ -1526,12 +1617,29 @@ KCommand *KWTableFrameSet::splitCell(uns if(colsDiff <0 && x==0) lastFrameSet->setColSpan(lastFrameSet->colSpan() - colsDiff); + addCell( lastFrameSet ); position(lastFrameSet); } } + + + // set new row and col-span. Use intermediate ints otherwise we get strange results as the + // intermediate result could be negative (which goes wrong with unsigned ints) + int r = (cell->rowSpan() +1) - intoRows; + if(r < 1) r=1; + cell->setRowSpan(r); + + int c = (cell->colSpan() + 1) - intoCols; + if(c < 1) c=1; + cell->setColSpan(c); + + printArrayDebug(); + position(cell); - addCellToArray(cell); + addCell(cell); + printArrayDebug(); + validate(); firstFrame->setSelected(true); firstFrame->createResizeHandles(); @@ -1544,93 +1652,38 @@ void KWTableFrameSet::viewFormatting( QP { } -/* checks the cells for missing cells or duplicates, will correct - mistakes. -*/ void KWTableFrameSet::validate() { - for (unsigned int j=0; j < getNumCells() ; j++) { - KWFrame *theFrame = getCell(j)->frame(0); - if(theFrame->frameBehavior()==KWFrame::AutoCreateNewFrame) { - theFrame->setFrameBehavior(KWFrame::AutoExtendFrame); - kdWarning() << "Table cell property frameBehavior was incorrect; fixed" << endl; - } - if(theFrame->newFrameBehavior()!=KWFrame::NoFollowup) { - kdWarning() << "Table cell property newFrameBehavior was incorrect; fixed" << endl; - theFrame->setNewFrameBehavior(KWFrame::NoFollowup); - } - } - - QPtrList misplacedCells; - - for(unsigned int row=0; row < getRows(); row++) { - for(unsigned int col=0; col firstRow() <= row && - m_cells.at( i )->firstCol() <= col && - m_cells.at( i )->rowAfter() > row && - m_cells.at( i )->colAfter() > col ) - { - if(found != -1) - { - kdWarning() << getName() << ": found duplicate cells when looking at row=" - << row << " col=" << col << ":" << endl; - kdWarning() << " " << found << " (" << m_cells.at(found)->firstRow() << ", " - << m_cells.at(found)->firstCol() << ") and " << i << " (" - << m_cells.at(i)->firstRow() << ", " << m_cells.at(i)->firstCol() - << ") moving one out of the way" << endl; - kdWarning() << "names: " << m_cells.at(found)->getName() << " , " - << m_cells.at(i)->getName() << endl; - - misplacedCells.append(m_cells.take(i--)); - } - found = i; - } - } - if(found == -1) { - kdWarning() << "Missing cell, creating a new one; ("<< row << "," << col<<")" << endl; - QString name = m_doc->generateFramesetName( i18n( "1 is table name, 2 is a number", "%1 Auto Added Cell %2" ).arg( getName() ) ); - Cell *cell = new Cell( this, row, col, name ); - KWFrame *theFrame = new KWFrame(cell, 10, 10, 20, 20, KWFrame::RA_NO ); - theFrame->setFrameBehavior(KWFrame::AutoExtendFrame); - theFrame->setNewFrameBehavior(KWFrame::NoFollowup); - cell->addFrame( theFrame,false ); - cell->setRowSpan(1); - cell->setColSpan(1); - addCell(cell); - position(cell); - } + for(CheckedIter cell(this); cell; ++cell) { + if(cell->colSpan() == 0 || cell->rowSpan() == 0) { + kdDebug(32004) << " KWTableFrameSet::validate(): zero dimension" << endl; + kdDebug(32004) << cell->firstRow() << " " << cell->firstCol() << " " << cell->rowSpan() + << " " << cell->colSpan() << endl; + } + + for(uint i = cell->firstRow(); i < cell->rowAfter(); ++i) { + + for(uint j = cell->firstCol(); j < cell->colAfter(); ++j) { + if( getCell(i,j) != cell.current() ) { + + QString str = QString("| 0x%1 ").arg( (unsigned long)cell.current(), 0, 16 ); + kdDebug(32004) << " KWTableFrameSet::validate() failed " << endl; + kdDebug(32004) << "at row: "<< i << " col: "<< j << " cell: "<< str << endl; + kdDebug(32004) << cell->firstRow() << " " << cell->firstCol() << " " << cell->rowSpan() + << " " << cell->colSpan() << endl; + printArrayDebug(); + } + } } } - while (! misplacedCells.isEmpty()) { - // append cell at bottom of table. - Cell *cell = misplacedCells.take(0); - removeCell(cell); - cell->setFirstRow(m_rows++); - cell->setFirstCol(0); - cell->setColSpan(getCols()); - cell->setRowSpan(1); - addCell(cell); - position(cell); - } } +// not sure where this method is used, it will be fixed soon bool KWTableFrameSet::contains( double mx, double my ) { - /* m_pageBoundaries is a list of integers. - The list contains an entry for each page and that entry points to the first cell - on that page. - The list contains integers of the index of the cell in the m_cells list. - - the following points to the first cell of the first page. - m_cells->at(m_pageBoundaries[0]) - - The last entry in the list points to the last+1 cell (the cell on a non-existing - extra page) Beware that this cell does no really exist! This entry is there so we - can always get the last cell on a page by substracting 1 from the firs cell of the - next page. (Well, in theory anyway, untill someone joins the last cell of a page ;) - */ + + (void) mx; + (void) my; +/* if(m_cells.count()==0) return false; if(m_pageBoundaries.count() ==0) @@ -1655,7 +1708,7 @@ bool KWTableFrameSet::contains( double m if(rect.contains(mx,my)) { return true; } - } + }*/ return false; } @@ -1708,6 +1761,12 @@ void KWTableFrameSet::createEmptyRegion( // Avoid iterating over all cells if we are out of view if ( !viewMode->normalToView( m_doc->zoomRect( boundingRect() ) ).intersects( crect ) ) return; + + QRect outerRect( viewMode->normalToView( m_doc->zoomRect( boundingRect() ))); + outerRect &= crect; + if ( !outerRect.isEmpty() ) + emptyRegion = emptyRegion.subtract( outerRect ); + QPtrListIterator frameIt = frameIterator(); for ( ; frameIt.current(); ++frameIt ) { @@ -1752,7 +1811,7 @@ void KWTableFrameSet::drawBorders( QPain //if(cell) kdDebug(32004) << "cell (" << cell->firstRow()<< "," << cell->firstCol() << ")" << endl; //else kdDebug(32004) << "cell: " << cell << endl; - if(cell && cell->firstRow() != (bottom ? row-1 : row)) + if(cell && cell->firstRow() != (bottom?row-1:row)) cell=0; if(startPos!=0 && (!cell || col == getCols() || ( @@ -1916,7 +1975,7 @@ void KWTableFrameSet::drawBorders( QPain int borderWidth = KoBorder::zoomWidthX( border->width(), m_doc, minborder ); painter.setPen(KoBorder::borderPen( *border, borderWidth, defaultBorderColor )); } - //kdDebug(32004) << "Paint: painter.drawVerticalLine(" << line.left() << "," << line.top() << "," << line.right() << "," << line.bottom() << ")\n"; + //kdDebug(32004) << "drawBorders(): painter.drawVerticalLine(" << line.left() << "," << line.top() << "," << line.right() << "," << line.bottom() << ")\n"; painter.drawLine( line.left(), line.top(), line.right(), line.bottom()); } @@ -1966,32 +2025,34 @@ void KWTableFrameSet::drawContents( QPai const QColorGroup & cg, bool onlyChanged, bool resetChanged, KWFrameSetEdit * edit, KWViewMode * viewMode ) { - for (unsigned int i=0; i < m_cells.count() ; i++) + for (TableIter cell(this) ; cell ; ++cell) { if (edit) { KWTableFrameSetEdit * tableEdit = static_cast(edit); - if ( tableEdit->currentCell() && m_cells.at(i) == tableEdit->currentCell()->frameSet() ) + if ( tableEdit->currentCell() && ((Cell*) cell) == tableEdit->currentCell()->frameSet() ) { - m_cells.at(i)->drawContents( painter, crect, cg, onlyChanged, resetChanged, tableEdit->currentCell(), viewMode ); + cell->drawContents( painter, crect, cg, onlyChanged, resetChanged, tableEdit->currentCell(), viewMode ); continue; } } - m_cells.at(i)->drawContents( painter, crect, cg, onlyChanged, resetChanged, 0L, viewMode ); + cell->drawContents( painter, crect, cg, onlyChanged, resetChanged, 0L, viewMode ); } drawBorders( *painter, crect, viewMode ); + kdDebug(32004) << "drawContents()" << endl; } -void KWTableFrameSet::zoom( bool forPrint ) { - for (unsigned int i =0; i < m_cells.count(); i++) { - m_cells.at(i)->zoom( forPrint ); - } +void KWTableFrameSet::zoom( bool forPrint ) +{ + for (TableIter cell(this) ; cell ; ++cell) + cell->zoom( forPrint ); } #if 0 -void KWTableFrameSet::preparePrinting( QPainter *painter, QProgressDialog *progress, int &processedParags ) { - for (unsigned int i =0; i < m_cells.count(); i++) { - m_cells.at(i)->preparePrinting( painter, progress, processedParags ); +void KWTableFrameSet::preparePrinting( QPainter *painter, QProgressDialog *progress, int &processedParags ) +{ + for (TableIter cell(this) ; cell ; ++cell) + cell->preparePrinting( painter, progress, processedParags ); } } #endif @@ -1999,9 +2060,8 @@ void KWTableFrameSet::preparePrinting( Q QDomElement KWTableFrameSet::save( QDomElement &parentElem, bool saveFrames ) { // When saving to a file, we don't have anything specific to the frameset to save. // Save the cells only. - for (unsigned int i =0; i < m_cells.count(); i++) { - m_cells.at(i)->save(parentElem, saveFrames); - } + for (TableIter cell(this) ; cell ; ++cell) + cell->save(parentElem, saveFrames); return QDomElement(); // No englobing element for tables... } @@ -2053,7 +2113,7 @@ KWTableFrameSet::Cell* KWTableFrameSet:: cell->load( framesetElem, loadFrames ); cell->setRowSpan(_rows); cell->setColSpan(_cols); - addCellToArray( cell ); // m_rows/m_cols have changed -> update array + addCell( cell ); // rowSpan()/m_cols have changed -> update array if(m_pageBoundaries.count() > 0) { unsigned int adjustment=0; @@ -2121,39 +2181,37 @@ KWTableFrameSet::Cell* KWTableFrameSet:: int KWTableFrameSet::paragraphs() { int paragraphs = 0; - for (unsigned int i =0; i < m_cells.count(); i++) { - paragraphs += m_cells.at(i)->paragraphs(); - } + for (TableIter cell(this) ; cell ; ++cell) + paragraphs += cell->paragraphs(); return paragraphs; } int KWTableFrameSet::paragraphsSelected() { int paragraphs = 0; - for (unsigned int i =0; i < m_cells.count(); i++) - paragraphs += m_cells.at(i)->paragraphsSelected(); + for (TableIter cell(this) ; cell ; ++cell) + paragraphs += cell->paragraphsSelected(); return paragraphs; } bool KWTableFrameSet::statistics( QProgressDialog *progress, ulong & charsWithSpace, ulong & charsWithoutSpace, ulong & words, ulong & sentences, ulong & syllables, ulong & lines, bool selected ) { - for (unsigned int i =0; i < m_cells.count(); i++) { - if( ! m_cells.at(i)->statistics( progress, charsWithSpace, charsWithoutSpace, words, sentences, syllables, lines, selected ) ) + for (TableIter cell(this) ; cell ; ++cell) + if( ! cell->statistics( progress, charsWithSpace, charsWithoutSpace, words, sentences, syllables, lines, selected ) ) { return false; } - } return true; } void KWTableFrameSet::finalize( ) { kdDebug(32004) << "KWTableFrameSet::finalize" << endl; - for(QPtrListIterator c(m_cells); c.current(); ++c) + for (TableIter cell(this) ; cell ; ++cell) { - position( c.current() ); - c.current()->finalize(); + position( cell ); + cell->finalize(); } recalcCols(); @@ -2163,9 +2221,9 @@ void KWTableFrameSet::finalize( ) { void KWTableFrameSet::setVisible( bool v ) { - for(QPtrListIterator cellIter(m_cells); cellIter.current(); ++cellIter) { - cellIter.current()->setVisible( v ); - } + for (TableIter cell(this) ; cell ; ++cell) + cell->setVisible( v ); + KWFrameSet::setVisible( v ); } @@ -2185,16 +2243,14 @@ bool KWTableFrameSet::canRemovePage( int void KWTableFrameSet::addTextFrameSets( QPtrList & lst, bool onlyReadWrite ) { - for(QPtrListIterator c(m_cells); c.current(); ++c) - if (!c.current()->textObject()->protectContent() || onlyReadWrite ) - lst.append(c.current()); + for (TableIter cell(this) ; cell ; ++cell) + if (!cell->textObject()->protectContent() || onlyReadWrite ) + lst.append(cell); } -void KWTableFrameSet::setLeftBorder(KoBorder newBorder) { - QPtrListIterator it( m_cells ); - Cell *cell; - while ( (cell = it.current()) != 0 ) { - ++it; +void KWTableFrameSet::setLeftBorder(KoBorder newBorder) +{ + for (TableIter cell(this) ; cell ; ++cell ) { if (cell->frame( 0 )->isSelected()) { Cell *cellLeft = cell->firstCol() > 0 ? getCell(cell->firstRow(), cell->firstCol()-1) : 0; if(!(cellLeft && cellLeft->frame(0)->isSelected())) { @@ -2204,13 +2260,11 @@ void KWTableFrameSet::setLeftBorder(KoBo } } -void KWTableFrameSet::setTopBorder(KoBorder newBorder) { - QPtrListIterator it( m_cells ); - Cell *cell; - while ( (cell = it.current()) != 0 ) { - ++it; +void KWTableFrameSet::setTopBorder(KoBorder newBorder) +{ + for (TableIter cell(this) ; cell ; ++cell ) { if (cell->frame( 0 )->isSelected()) { - Cell *cellAbove = cell->firstRow() > 0 ? getCell(cell->firstRow()-1, cell->firstCol()) : 0; + Cell *cellAbove = cell->firstRow() > 0 ? getCell(cell->firstRow()-1, cell->firstCol()) : 0; if(!(cellAbove && cellAbove->frame(0)->isSelected())) { cell->setTopBorder(newBorder); } @@ -2219,11 +2273,9 @@ void KWTableFrameSet::setTopBorder(KoBor recalcRows(); } -void KWTableFrameSet::setBottomBorder(KoBorder newBorder) { - QPtrListIterator it( m_cells ); - Cell *cell; - while ( (cell = it.current()) != 0 ) { - ++it; +void KWTableFrameSet::setBottomBorder(KoBorder newBorder) +{ + for (TableIter cell(this) ; cell ; ++cell ) { if (cell->frame( 0 )->isSelected()) { Cell *otherCell = cell->firstRow() < getRows() ? getCell(cell->firstRow()+1, cell->firstCol()) : 0; if(!(otherCell && otherCell->frame(0)->isSelected())) { @@ -2234,11 +2286,9 @@ void KWTableFrameSet::setBottomBorder(Ko recalcRows(); } -void KWTableFrameSet::setRightBorder(KoBorder newBorder) { - QPtrListIterator it( m_cells ); - Cell *cell; - while ( (cell = it.current()) != 0 ) { - ++it; +void KWTableFrameSet::setRightBorder(KoBorder newBorder) +{ + for (TableIter cell(this) ; cell ; ++cell ) { if (cell->frame( 0 )->isSelected()) { Cell *otherCell = cell->firstCol() < getCols() ? getCell(cell->firstRow(), cell->firstCol()+1) : 0; if(!(otherCell && otherCell->frame(0)->isSelected())) { @@ -2250,11 +2300,8 @@ void KWTableFrameSet::setRightBorder(KoB KCommand *KWTableFrameSet::setProtectContent( bool _protect ) { - QPtrListIterator it( m_cells ); - Cell *cell; KMacroCommand *macro = 0L; - while ( (cell = it.current()) != 0 ) { - ++it; + for (TableIter cell(this) ; cell ; ++cell ) { if (cell->frame( 0 )->isSelected()) { if ( cell->protectContent() != _protect ) { @@ -2269,37 +2316,38 @@ KCommand *KWTableFrameSet::setProtectCon return macro; } + KWTextFrameSet* KWTableFrameSet::nextTextObject( KWFrameSet *obj ) { - int pos = -1; + bool found = false; KWTableFrameSet::Cell *tmp = dynamic_cast(obj); - if ( tmp ) - pos=m_cells.findNextRef(tmp); - if(pos !=-1) - { - KWFrameSet *frm=0L; - for ( frm=m_cells.at(pos); frm != 0; frm=m_cells.next() ){ - KWTextFrameSet *newFrm = frm->nextTextObject( obj ); - if(newFrm && newFrm->textObject()->needSpellCheck()) - return newFrm; - } + + // make sure we have this cell + if ( tmp ) { + for(TableIter i(this); i; ++i) { + if(i.current() == tmp) { + found = true; + break; + } + } } - else - { - KWFrameSet *frm=0L; - for ( frm=m_cells.first(); frm != 0; frm=m_cells.next() ){ - KWTextFrameSet *newFrm = frm->nextTextObject( obj ); - if(newFrm && newFrm->textObject()->needSpellCheck()) - return newFrm; - } + + TableIter iter(this); + if(found) + iter.goToCell(tmp); + + for(; iter; ++iter) { + KWTextFrameSet *newFrm = iter->nextTextObject( obj ); + if(newFrm && newFrm->textObject()->needSpellCheck()) + return newFrm; } + return 0L; } void KWTableFrameSet::setZOrder() { - Cell *cell; - for( cell=m_cells.first();cell;cell=m_cells.next() ) { + for( TableIter cell(this) ; cell ; ++cell ) { cell->setZOrder(); } @@ -2311,11 +2359,11 @@ void KWTableFrameSet::convertTableToText QDomElement elem = domDoc.createElement( "PARAGRAPHS" ); domDoc.appendChild( elem ); QString text; - for (unsigned int i =0; i < m_cells.count(); i++) + for (TableIter cell(this); cell; ++cell) { - m_cells.at(i)->textDocument()->selectAll( KoTextDocument::Temp ); - text += m_cells.at(i)->copyTextParag( elem, KoTextDocument::Temp ); - m_cells.at(i)->textDocument()->removeSelection( KoTextDocument::Temp ); + cell->textDocument()->selectAll( KoTextDocument::Temp ); + text += cell->copyTextParag( elem, KoTextDocument::Temp ); + cell->textDocument()->removeSelection( KoTextDocument::Temp ); } KWTextDrag *kd = new KWTextDrag( 0L ); kd->setPlain( text ); @@ -2374,6 +2422,7 @@ KWTableFrameSet::Cell::Cell( KWTableFram m_col = col; m_rows = 1; m_cols = 1; + m_isJoinedCell = false; setGroupManager( table ); table->addCell( this ); m_name = i18n("Hello dear translator :), 1 is the table name, 2 and 3 are row and column", "%1 Cell %2,%3") @@ -2387,6 +2436,7 @@ KWTableFrameSet::Cell::Cell( KWTableFram m_col = original.m_col; m_rows = original.m_rows; m_cols = original.m_cols; + m_isJoinedCell = original.m_isJoinedCell; setName(original.m_name+'_'); // unicity problem ! setGroupManager( table ); table->addCell( this ); @@ -2405,8 +2455,8 @@ bool KWTableFrameSet::Cell::containsCell { return ( m_row <= row && m_col <= col && - m_row + m_rows > row && - m_col + m_cols > col ); + rowAfter() > row && + colAfter() > col ); } void KWTableFrameSet::Cell::addFrame(KWFrame *_frame, bool recalc) { @@ -2654,7 +2704,7 @@ void KWTableFrameSetEdit::keyPressEvent( fs=tableFrame->getCell(row,col); // Not needed. getCell gives us the right one already //if(fs && (int)fs->m_col != col) { // Merged cell - // fs=tableFrame->getCell( row, col - fs->m_cols + 1 ); + // fs=tableFrame->getCell( row, col - fs->colSpan() + 1 ); //} } } @@ -2770,4 +2820,186 @@ void KWTableFrameSet::Row::removeCell( C m_cellArray.remove( col ); } +template<> +KWTableFrameSet::Cell* +KWTableFrameSet::TableIterator::operator++() +{ + if(!m_cell) return 0; + + Cell *ret = m_cell; + + do{ + // check for end of row first + if(m_table->getCell(m_row,m_col)->lastCol() >= m_limit[RIGHT] ) { + // now check for end of column + if (m_row >= m_limit[LOW]){ + // at end of traversal + m_cell = 0; + break; + } + else { + // goto first grid position in next row + m_row += 1; + m_col = m_limit[LEFT]; + } + } + else { + // goto next cell in row + m_col = m_table->getCell(m_row, m_col)->colAfter(); + } + + } while( ! (m_cell = m_table->getCell(m_row,m_col))->isFirstGridPosnFast(m_row,m_col)); + + return ret; +} + +template<> +KWTableFrameSet::Cell* +KWTableFrameSet::TableIterator::operator++() +{ + if(!m_cell) return 0; + + Cell *ret = m_cell; + // check for end of row + if(m_col == m_limit[RIGHT]) { + if(m_row == m_limit[LOW]) { // end of traversal + m_row = 0; + m_col = 0; + m_cell = 0; + } + else { // go to next row + m_row += 1; + m_col = m_limit[LEFT]; + m_cell = m_table->getCell(m_row, m_col); + } + } + else { // move to next cell in row + m_col += 1; + m_cell = m_table->getCell(m_row, m_col); + } + + return ret; +} + +KWTableFrameSet::MarkedIterator::MarkedIterator(KWTableFrameSet *table) : + GridIter(table) +{ + // clear all the cell marks + for(GridIter cell(table); cell; ++cell) + cell->clearMark(); + + if ( current() ) { +// kdDebug() << "MarkedIterator: visit: " +// << QString("| 0x%1 ").arg((unsigned long)current(), 0, 16) << endl; + current()->setMark(); + } +} + +KWTableFrameSet::Cell * +KWTableFrameSet::MarkedIterator::operator++() +{ + Cell *ret = GridIter::operator++(); + + while ( current() && current()->marked() ) { + GridIter::operator++(); + } + if ( current() ) { +// kdDebug() << "MarkedIterator: visit: " +// << QString("| 0x%1 ").arg((unsigned long)current(), 0, 16) << endl; + current()->setMark(); + } + return ret; +} + +template<> +KWTableFrameSet::TableIterator::TableIterator(KWTableFrameSet *table): + m_table(table) +{ + Q_ASSERT(m_table); + set_limits(0, m_table->getCols() - 1, 0, m_table->getRows() - 1); + + Cell *c = 0; + for(uint i = m_limit[HIGH]; i <= m_limit[LOW]; ++i) + for(uint j = m_limit[LEFT]; j <= m_limit[RIGHT]; ++j) { + + c = m_table->getCell(i,j); + if(c) c->clearMark(); + } + toFirstCell(); +} + +template<> +KWTableFrameSet::Cell* +KWTableFrameSet::TableIterator::operator++ () +{ + + Cell *ret = m_cell; + if(!ret) return 0; + + ret->setMark(); + m_cell = 0; + uint i = m_row; uint j = m_col; + + for(; i <= m_limit[LOW]; ++i) { + + for(j = 0; j <= m_limit[RIGHT]; ++j) { + m_cell = m_table->getCell(i,j); + if( m_cell && !m_cell->marked() ){ + m_row = i; m_col = j; + goto out; + } + else if(i == m_limit[LOW] && j == m_limit[RIGHT]){ + m_cell = 0; + goto out; + } + } + } + + out: + return ret; +} + +template<> +KWTableFrameSet::Cell* +KWTableFrameSet::TableIterator::toFirstCell () +{ + m_cell = 0; + for(uint i = m_limit[HIGH]; i <= m_limit[LOW]; ++i) + for(uint j = m_limit[LEFT]; j <= m_limit[RIGHT]; ++j) { + m_cell = m_table->getCell(i,j); + if(m_cell) { + m_row = i; m_col = j; + goto out; + } + } + + out: + return m_cell; +} + +RemovedRow::RemovedRow() : + m_row(0), m_index(0), m_rowHeight(0.0) +{ + +} + +RemovedRow::~RemovedRow() +{ + // free cells as well ??? + delete m_row; +} + +KWTableFrameSet::Row *RemovedRow::takeRow() +{ + Q_ASSERT(m_row); + KWTableFrameSet::Row *ret = m_row; + m_row = 0; + return ret; +} + +RemovedColumn::RemovedColumn() + : m_column(), m_removed(), m_index(0), m_width(0), m_initialized(false){ } + + + #include "kwtableframeset.moc" diff -uNp --exclude-from=/home/carl/kde-devel/.diffignore kword/kwtableframeset.h kword-m_cells/kwtableframeset.h --- kword/kwtableframeset.h 2003-05-24 10:48:43.000000000 +1000 +++ kword-m_cells/kwtableframeset.h 2003-06-08 13:09:54.000000000 +1000 @@ -30,6 +30,7 @@ DESCRIPTION #include #include #include +#include #include #include #include @@ -40,6 +41,8 @@ class QPainter; class KWAnchor; class KWordFrameSetIface; +class RemovedRow; +class RemovedColumn; /** * Class: KWTableFrameSet * @@ -64,6 +67,12 @@ public: unsigned int m_row, m_col; unsigned int m_rows, m_cols; + bool m_isJoinedCell; + bool m_marker; + void calcIfJoinedCell() { + m_isJoinedCell = ( (m_rows > 1) || (m_cols > 1) ); + } + public: // constructor Cell( KWTableFrameSet *table, unsigned int row, unsigned int col, const QString & name = QString::null ); @@ -83,13 +92,25 @@ public: void setFirstRow(uint row) { m_row = row; } void setFirstCol(uint col) { m_col = col; } - void setRowSpan(uint rows) { m_rows = rows; } - void setColSpan(uint cols) { m_cols = cols; } + void setRowSpan(uint rows) { + m_rows = rows; + calcIfJoinedCell(); + } + void setColSpan(uint cols) { + m_cols = cols; + calcIfJoinedCell(); + } + bool isFirstGridPosn(uint row, uint col) const { + return (row == m_row) && (col == m_col); + } + + bool isFirstGridPosnFast(uint row, uint col) const { + if(!m_isJoinedCell) return true; + return (row == m_row) && (col == m_col); + } virtual void addFrame(KWFrame *_frame, bool recalc = true); - uint getRow() const {return m_row;} - uint getColumn() const {return m_col;} KWTableFrameSet *table() const { return grpMgr; } bool isAboveOrLeftOf( unsigned row, unsigned col ) const; bool containsCell( unsigned row, unsigned col ) const; @@ -107,14 +128,20 @@ public: * set zorder for all frames in this cell */ void setZOrder(); + bool isJoinedCell() const { return m_isJoinedCell; } + void clearMark() { m_marker = false; } + void setMark() { m_marker = true; } + bool marked() { return m_marker; } + }; friend class Cell; // Represents a row, for direct access to cells with m_rowArray[row][column] class Row { public: - Cell* operator[] ( int i ) const { return i < (int)size() ? m_cellArray[i] : 0; } + Cell* operator[] ( uint i ) const { return i < size() ? m_cellArray[i] : 0; } uint size() const { return m_cellArray.size(); } + uint count() const { return m_cellArray.count(); } void addCell( Cell *cell ); void removeCell( Cell* cell ); @@ -125,6 +152,114 @@ public: }; + /** The three different types of TableIterators */ + enum {VISIT_GRID = 1, VISIT_CELL = 2, CHECKED = 3}; + + /** + All the TableIterator templates are the same, except for the pre-increment + operator (operator++). There is a specialised version of this + operator method for each iterator type: + + VISIT_GRID: This iterator visits each grid position once, ie every + location in the m_rowArray rows. When some cells are joined, this + iterator will visit those cells more than once. + + VISIT_CELL: This iterator visits each cell in the table once, whether + or not some of the cells are joined. If you want to visit all the cells + fast and perform some read-only operation, this is the one to use. + + CHECKED: Also visits each cell once, but has some other benefits. Slower. + + Note that all the iterators have restrictions on the state that the + table data structures are in before and while they are being used. + This includes m_rowArray, the Rows and Cells but not m_colPositions and + m_rowPositions, as they are not used during the traversal. + The conditions include: + ( A ) All positions in m_rowArray must be occupied by a valid cell, ie must + not be null. + ( B ) The Cell instance variables (m_row, m_rows, etc) must correctly + correspond to where the cells are in m_rowArray. + ( C ) The m_rows and m_cols instance variables of the table are also correct. + Taken together, these conditions are pretty much equivalent to the + validate() function passing. These conditions may not hold in the middle + of a method when table data structures are being manipulated. + + This table shows what conditions are necessary for each type of iterator: + + A B C + TableIterator | x | | x | + TableIterator | x | x | x | + TableIterator | | | x | + MarkedIterator | x | | x | + + The only iterator that can be used when their are null positions in the + table is the checked iterator. + Note that both the Checked and Marked Iterators traverse the table twice, + once to clear the m_marked members in the cells (done in constructor) and + then again to do the actual traversal. Because they use m_marked, only one + of these iterators can be used at once. + + Don't use these classes directly in code, use the provided typedefs. That + makes it easy to do more crazy template stuff later on. :-) Templates + are used here rather than inheritance to avoid virtual call overhead. + */ + template + class TableIterator { + public: + /** + * @param The table to iterate over. The current item is set to the Cell + * at row 0, column 0 + */ + TableIterator (KWTableFrameSet *table); + + Cell* toFirstCell (); + void goToCell(Cell*); + + operator Cell* () const { return m_cell; } + Cell * current() const; + Cell * operator->() { return m_cell; } + Cell * operator++ (); + + protected: + KWTableFrameSet *m_table; + void set_limits(uint left, uint right, uint high, uint low) + { + m_limit[LEFT] = left; + m_limit[RIGHT] = right; + m_limit[HIGH] = high; + m_limit[LOW] = low; + } + private: + + Cell *m_cell; + uint m_row; + uint m_col; + + enum Direction {LEFT, RIGHT, HIGH, LOW}; + static const uint DIRECTION_SIZE = 4; + uint m_limit[DIRECTION_SIZE]; + }; + + typedef TableIterator TableIter; + typedef TableIterator GridIter; + typedef TableIterator CheckedIter; + + /** + * This iterator does not look at the Cell instance variables + * during traversal, (except m_marker), so they can be safely + * changed during the traversal. However, to the user it does + * not visit every grid position, it visits each cell once. + * (in spite of the fact that it inherits from a grid-visiting + * iterator . + * Only one MarkedIterator can be used at once. See TableIterator + */ + class MarkedIterator : public GridIter { + public: + MarkedIterator(KWTableFrameSet *table); + Cell *operator++(); // overriden from base but not virtual + + }; + /** The type of frameset. Use this to differentiate between different instantiations of * the framesets. Each implementation will return a different frameType. @@ -158,7 +293,6 @@ public: KWFrameSetEdit *, KWViewMode *, bool ) {} // Frameset management - Cell *getCell( int i ) { return m_cells.at( i ); } Cell *getCell( unsigned int row, unsigned int col ); Cell *getCellByPos( double x, double y ); @@ -213,13 +347,13 @@ public: int rowEdgeAt( double y ) const; /** returns the number of rows */ - unsigned int getRows()const { return m_rows; } + unsigned int getRows() const { return m_rows; } /** returns the number of columns */ - unsigned int getCols()const { return m_colPositions.count()-1; } + unsigned int getCols() const { return m_cols; } /** returns the number of cells the table contains, this includes * temporary headers. */ - unsigned int getNumCells()const { return m_cells.count(); } + unsigned int getNumCells()const { return m_nr_cells; } /** returns the fact if one cell (==frame) has been selected */ bool hasSelectedFrame(); @@ -265,21 +399,27 @@ public: bool isOneSelected( unsigned int &row, unsigned int &col ); /** insert a row of new cells, use the getCols() call to decide how many cells are created */ - void insertRow( unsigned int _idx,QPtrList listFrameSet=QPtrList(),QPtrListlistFrame=QPtrList(), bool _recalc = true, bool _removeable = false ); + void insertNewRow( uint _idx, bool _recalc = true, bool _removeable = false ); /** insert a column of new cells use the getRows() call to decide how many cells are created */ - void insertCol( unsigned int _idx,QPtrList listFrameSet=QPtrList(), QPtrList listFrame=QPtrList(), double width = KWTableFrameSet::m_sDefaultColWidth); + void insertNewCol( uint _idx, double width = KWTableFrameSet::m_sDefaultColWidth); - /** remove all the cells in a certain row */ - void deleteRow( unsigned int _idx, bool _recalc = true ); - /** remove all the cells in a certain col */ - void deleteCol( unsigned int _idx); + /** Remove all the cells in a certain row */ + void deleteRow( uint _idx, RemovedRow &rr, bool _recalc = true); + + /** remove all the cells in a certain column */ + void deleteCol( uint _idx, RemovedColumn &rc); + + /** replace a row that was removed with deleteRow() */ + void reInsertRow(RemovedRow &row); + /** replace a column that was removed with deleteCol() */ + void reInsertCol(RemovedColumn &col); // the boolean actually works, but is not saved (to xml) yet :( void setShowHeaderOnAllPages( bool s ) { m_showHeaderOnAllPages = s; } - bool getShowHeaderOnAllPages()const { return m_showHeaderOnAllPages; } + bool getShowHeaderOnAllPages() const { return m_showHeaderOnAllPages; } /** redraw contents of temp headers. */ - bool hasTempHeaders()const { return m_hasTmpHeaders; } + bool hasTempHeaders() const { return m_hasTmpHeaders; } /** release the constrains of the table and allow all frames to be * edited apart from each other. (ps. there is no way back..) */ @@ -292,7 +432,9 @@ public: /** merge cells to one cell. Will loose all text not in top-left cell */ KCommand *joinCells(unsigned int colBegin=0,unsigned int rowBegin=0, unsigned int colEnd=0,unsigned int rowEnd=0); /** split selected cell into a number of cells */ - KCommand * splitCell(unsigned int intoRows, unsigned int intoCols, int _col=-1, int _row=-1,QPtrList listFrameSet=QPtrList(),QPtrListlistFrame=QPtrList()); + KCommand * splitCell(unsigned int intoRows, unsigned int intoCols, int _col=-1, int _row=-1, + QPtrList listFrameSet=QPtrList(), + QPtrListlistFrame=QPtrList()); /** display formatting information */ void viewFormatting( QPainter &painter, int zoom ); @@ -399,12 +541,24 @@ private: /** returns the absolute top-position of the row in the grid */ double getPositionOfRow(unsigned int row, bool bottom=false); - unsigned int m_rows; + void insertEmptyColumn(uint index); + /** + * insert a row in m_rowArray at position index. rows after + * the inserted row are moved back. + */ + void insertRowVector(uint index, Row *row); + /** + * remove the row from m_rowArray at position index. + * rows after are moved forward + * @return the removed row + */ + Row* removeRowVector(uint index); + + unsigned int m_rows, m_cols, m_nr_cells; bool m_showHeaderOnAllPages; bool m_hasTmpHeaders; bool m_active; - QPtrVector< Row > m_rowArray; // the new data structure - QPtrList m_cells; // the old data structure (will disappear) + QPtrVector< Row > m_rowArray; /** The list of page boundaries. * Each page the table spans has an entry in this list which points to the last _line_ @@ -413,10 +567,103 @@ private: * empty. */ QValueList m_pageBoundaries; - unsigned int redrawFromCol; + unsigned int m_redrawFromCol; QValueList m_rowPositions, m_colPositions; }; + +// all three templates specialise operator++ +template<> +KWTableFrameSet::Cell* +KWTableFrameSet::TableIterator::operator++ (); + +template<> +KWTableFrameSet::Cell* +KWTableFrameSet::TableIterator::operator++ (); + +template<> +KWTableFrameSet::Cell* +KWTableFrameSet::TableIterator::operator++ (); + +template +KWTableFrameSet::TableIterator::TableIterator(KWTableFrameSet *table) : + m_table(table) +{ + Q_ASSERT(m_table); + set_limits(0, m_table->getCols() - 1, 0, m_table->getRows() - 1); + toFirstCell(); +} + +// CHECKED specialises the constructor +template<> +KWTableFrameSet::TableIterator::TableIterator(KWTableFrameSet *table); + + +template +KWTableFrameSet::Cell* +KWTableFrameSet::TableIterator::toFirstCell (){ + m_cell = m_table->getCell(m_limit[HIGH], m_limit[LEFT]); + Q_ASSERT(m_cell); + m_row = m_cell->firstRow(); + m_col = m_cell->firstCol(); + return m_cell; +} + +template +void +KWTableFrameSet::TableIterator::goToCell(KWTableFrameSet::Cell *cell) +{ + m_cell = cell; + m_row = m_cell->firstRow(); + m_col = m_cell->firstCol(); +} + +// CHECKED specialises to first cell +template<> +KWTableFrameSet::Cell* +KWTableFrameSet::TableIterator::toFirstCell (); + + +template +KWTableFrameSet::Cell* +KWTableFrameSet::TableIterator::current() const { + return m_cell; +} + +/** + * RemovedRow and RemovedColumn implement the Memento design pattern + */ +class RemovedRow { + + KWTableFrameSet::Row *m_row; + // The row index that this row used to occupy + uint m_index; + double m_rowHeight; + + uint index() const { return m_index; } + double height() const { return m_rowHeight; } + KWTableFrameSet::Row *takeRow(); + KWTableFrameSet::Row *row() { return m_row; } + + friend class KWTableFrameSet; +public: + RemovedRow(); + ~RemovedRow(); +}; + +class RemovedColumn { + + QPtrList m_column; + QValueList m_removed; + uint m_index; + double m_width; + bool m_initialized; + + friend class KWTableFrameSet; +public: + RemovedColumn(); +}; + /** * The object created to edit this table - in fact at a given moment, * it edits one cell (frameset) of the table, the one in which the cursor is. diff -uNp --exclude-from=/home/carl/kde-devel/.diffignore kword/kwview.cc kword-m_cells/kwview.cc --- kword/kwview.cc 2003-06-08 01:40:05.000000000 +1000 +++ kword-m_cells/kwview.cc 2003-06-08 12:41:45.000000000 +1000 @@ -3839,7 +3839,7 @@ int KWView::tableDeleteRow(const QValueL KMacroCommand *macro = new KMacroCommand(i18n("Remove Rows")); - for (uint i = 0 ; i < rows.count() ; i++) { + for (int i = rows.count() - 1; i >= 0 ; i--) { KWRemoveRowCommand *cmd = new KWRemoveRowCommand( i18n("Remove Row"), table, rows[i] ); macro->addCommand(cmd); @@ -3865,7 +3865,7 @@ int KWView::tableDeleteCol(const QValueL KMacroCommand *macro = new KMacroCommand(i18n("Remove Columns")); - for (uint i = 0 ; i < cols.count() ; i++) { + for (int i = cols.count() - 1; i >= 0; i--) { KWRemoveColumnCommand *cmd = new KWRemoveColumnCommand( i18n("Remove Column"), table, cols[i] ); macro->addCommand(cmd); diff -uNp --exclude-from=/home/carl/kde-devel/.diffignore kword/kwview.h kword-m_cells/kwview.h --- kword/kwview.h 2003-05-25 21:45:47.000000000 +1000 +++ kword-m_cells/kwview.h 2003-06-08 15:25:50.000000000 +1000 @@ -265,6 +265,7 @@ public slots: void tableDeleteCol(); void tableJoinCells(); void tableSplitCells(); + void tableSplitCells(int col, int row); void tableProtectCells(); void tableUngroupTable(); void tableDelete(); @@ -472,7 +473,6 @@ protected: void borderShowValues(); void borderSet(); - void tableSplitCells(int col, int row); void startKSpell(); void clearSpellChecker(); Common subdirectories: kword/.libs and kword-m_cells/.libs Common subdirectories: kword/mailmerge and kword-m_cells/mailmerge Common subdirectories: kword/pics and kword-m_cells/pics Common subdirectories: kword/templates and kword-m_cells/templates Common subdirectories: kword/toolbar and kword-m_cells/toolbar